Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
22d7e53b
Unverified
Commit
22d7e53b
authored
Sep 22, 2020
by
Ralph Pichler
Committed by
GitHub
Sep 22, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add cheque signing (#720)
parent
b3607c89
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
638 additions
and
88 deletions
+638
-88
start.go
cmd/bee/cmd/start.go
+8
-1
clef.go
pkg/crypto/clef/clef.go
+29
-9
clef_test.go
pkg/crypto/clef/clef_test.go
+64
-2
typeddata.go
pkg/crypto/eip712/typeddata.go
+50
-0
signer.go
pkg/crypto/signer.go
+70
-26
signer_test.go
pkg/crypto/signer_test.go
+89
-0
node.go
pkg/node/node.go
+8
-0
cheque.go
pkg/settlement/swap/chequebook/cheque.go
+98
-0
cheque_test.go
pkg/settlement/swap/chequebook/cheque_test.go
+103
-0
chequebook.go
pkg/settlement/swap/chequebook/chequebook.go
+59
-9
chequebook_test.go
pkg/settlement/swap/chequebook/chequebook_test.go
+2
-0
common_test.go
pkg/settlement/swap/chequebook/common_test.go
+31
-0
factory.go
pkg/settlement/swap/chequebook/factory.go
+11
-11
init.go
pkg/settlement/swap/chequebook/init.go
+4
-3
chequebook.go
pkg/settlement/swap/chequebook/mock/chequebook.go
+4
-0
transaction.go
pkg/settlement/swap/chequebook/transaction.go
+8
-8
transaction_test.go
pkg/settlement/swap/chequebook/transaction_test.go
+0
-19
No files found.
cmd/bee/cmd/start.go
View file @
22d7e53b
...
...
@@ -9,6 +9,7 @@ import (
"context"
"fmt"
"io/ioutil"
"os"
"os/signal"
"path/filepath"
...
...
@@ -17,6 +18,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/accounts/external"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/crypto/clef"
"github.com/ethersphere/bee/pkg/keystore"
...
...
@@ -143,7 +145,12 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
return
err
}
signer
,
err
=
clef
.
NewSigner
(
externalSigner
,
crypto
.
Recover
)
clefRPC
,
err
:=
rpc
.
Dial
(
endpoint
)
if
err
!=
nil
{
return
err
}
signer
,
err
=
clef
.
NewSigner
(
externalSigner
,
clefRPC
,
crypto
.
Recover
)
if
err
!=
nil
{
return
err
}
...
...
pkg/crypto/clef/clef.go
View file @
22d7e53b
...
...
@@ -14,8 +14,10 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/crypto/eip712"
)
var
(
...
...
@@ -23,20 +25,26 @@ var (
clefRecoveryMessage
=
[]
byte
(
"public key recovery message"
)
)
// ExternalSignerInterface is the interface for the clef client from go-ethereum
// ExternalSignerInterface is the interface for the clef client from go-ethereum
.
type
ExternalSignerInterface
interface
{
SignData
(
account
accounts
.
Account
,
mimeType
string
,
data
[]
byte
)
([]
byte
,
error
)
SignTx
(
account
accounts
.
Account
,
tx
*
types
.
Transaction
,
chainID
*
big
.
Int
)
(
*
types
.
Transaction
,
error
)
Accounts
()
[]
accounts
.
Account
}
// Client is the interface for rpc.RpcClient.
type
Client
interface
{
Call
(
result
interface
{},
method
string
,
args
...
interface
{})
error
}
type
clefSigner
struct
{
client
Client
// low-level rpc client to clef as ExternalSigner does not implement account_signTypedData
clef
ExternalSignerInterface
account
accounts
.
Account
// the account this signer will use
pubKey
*
ecdsa
.
PublicKey
// the public key for the account
}
// DefaultIpcPath returns the os-dependent default ipc path for clef
// DefaultIpcPath returns the os-dependent default ipc path for clef
.
func
DefaultIpcPath
()
(
string
,
error
)
{
socket
:=
"clef.ipc"
// on windows clef uses top level pipes
...
...
@@ -58,9 +66,9 @@ func DefaultIpcPath() (string, error) {
return
filepath
.
Join
(
home
,
".clef"
,
socket
),
nil
}
// NewSigner creates a new connection to the signer at endpoint
// As clef does not expose public keys it signs a test message to recover the public key
func
NewSigner
(
clef
ExternalSignerInterface
,
recoverFunc
crypto
.
RecoverFunc
)
(
signer
crypto
.
Signer
,
err
error
)
{
// NewSigner creates a new connection to the signer at endpoint
.
// As clef does not expose public keys it signs a test message to recover the public key
.
func
NewSigner
(
clef
ExternalSignerInterface
,
client
Client
,
recoverFunc
crypto
.
RecoverFunc
)
(
signer
crypto
.
Signer
,
err
error
)
{
// get the list of available ethereum accounts
clefAccounts
:=
clef
.
Accounts
()
if
len
(
clefAccounts
)
==
0
{
...
...
@@ -83,29 +91,41 @@ func NewSigner(clef ExternalSignerInterface, recoverFunc crypto.RecoverFunc) (si
}
return
&
clefSigner
{
client
:
client
,
clef
:
clef
,
account
:
account
,
pubKey
:
pubKey
,
},
nil
}
// PublicKey returns the public key recovered during creation
// PublicKey returns the public key recovered during creation
.
func
(
c
*
clefSigner
)
PublicKey
()
(
*
ecdsa
.
PublicKey
,
error
)
{
return
c
.
pubKey
,
nil
}
// SignData signs with the text/plain type which is the standard Ethereum prefix method
// SignData signs with the text/plain type which is the standard Ethereum prefix method
.
func
(
c
*
clefSigner
)
Sign
(
data
[]
byte
)
([]
byte
,
error
)
{
return
c
.
clef
.
SignData
(
c
.
account
,
accounts
.
MimetypeTextPlain
,
data
)
}
// SignTx signs an ethereum transaction
// SignTx signs an ethereum transaction
.
func
(
c
*
clefSigner
)
SignTx
(
transaction
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
{
// chainId is nil here because it is set on the clef side
return
c
.
clef
.
SignTx
(
c
.
account
,
transaction
,
nil
)
}
// EthereumAddress returns the ethereum address this signer uses
// EthereumAddress returns the ethereum address this signer uses
.
func
(
c
*
clefSigner
)
EthereumAddress
()
(
common
.
Address
,
error
)
{
return
c
.
account
.
Address
,
nil
}
// SignTypedData signs data according to eip712.
func
(
c
*
clefSigner
)
SignTypedData
(
typedData
*
eip712
.
TypedData
)
([]
byte
,
error
)
{
var
sig
hexutil
.
Bytes
err
:=
c
.
client
.
Call
(
&
sig
,
"account_signTypedData"
,
c
.
account
.
Address
,
typedData
)
if
err
!=
nil
{
return
nil
,
err
}
return
sig
,
nil
}
pkg/crypto/clef/clef_test.go
View file @
22d7e53b
...
...
@@ -13,9 +13,11 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/crypto/clef"
"github.com/ethersphere/bee/pkg/crypto/eip712"
)
type
mockClef
struct
{
...
...
@@ -61,7 +63,7 @@ func TestNewClefSigner(t *testing.T) {
signature
:
testSignature
,
}
signer
,
err
:=
clef
.
NewSigner
(
mock
,
func
(
signature
,
data
[]
byte
)
(
*
ecdsa
.
PublicKey
,
error
)
{
signer
,
err
:=
clef
.
NewSigner
(
mock
,
nil
,
func
(
signature
,
data
[]
byte
)
(
*
ecdsa
.
PublicKey
,
error
)
{
if
!
bytes
.
Equal
(
testSignature
,
signature
)
{
t
.
Fatalf
(
"wrong data used for recover. expected %v got %v"
,
testSignature
,
signature
)
}
...
...
@@ -102,7 +104,7 @@ func TestClefNoAccounts(t *testing.T) {
accounts
:
[]
accounts
.
Account
{},
}
_
,
err
:=
clef
.
NewSigner
(
mock
,
nil
)
_
,
err
:=
clef
.
NewSigner
(
mock
,
nil
,
nil
)
if
err
==
nil
{
t
.
Fatal
(
"expected ErrNoAccounts error if no accounts"
)
}
...
...
@@ -110,3 +112,63 @@ func TestClefNoAccounts(t *testing.T) {
t
.
Fatalf
(
"expected ErrNoAccounts error but got %v"
,
err
)
}
}
type
mockRpc
struct
{
call
func
(
result
interface
{},
method
string
,
args
...
interface
{})
error
}
func
(
m
*
mockRpc
)
Call
(
result
interface
{},
method
string
,
args
...
interface
{})
error
{
return
m
.
call
(
result
,
method
,
args
...
)
}
func
TestClefTypedData
(
t
*
testing
.
T
)
{
key
,
err
:=
crypto
.
GenerateSecp256k1Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
publicKey
:=
&
key
.
PublicKey
signature
:=
common
.
FromHex
(
"0xabcdef"
)
account
:=
common
.
HexToAddress
(
"21b26864067deb88e2d5cdca512167815f2910d3"
)
typedData
:=
&
eip712
.
TypedData
{
PrimaryType
:
"MyType"
,
}
signer
,
err
:=
clef
.
NewSigner
(
&
mockClef
{
accounts
:
[]
accounts
.
Account
{
{
Address
:
account
,
},
},
signature
:
make
([]
byte
,
65
),
},
&
mockRpc
{
call
:
func
(
result
interface
{},
method
string
,
args
...
interface
{})
error
{
if
method
!=
"account_signTypedData"
{
t
.
Fatalf
(
"called wrong method. was %s"
,
method
)
}
if
args
[
0
]
.
(
common
.
Address
)
!=
account
{
t
.
Fatalf
(
"called with wrong account. was %x, wanted %x"
,
args
[
0
]
.
(
common
.
Address
),
account
)
}
if
args
[
1
]
.
(
*
eip712
.
TypedData
)
!=
typedData
{
t
.
Fatal
(
"called with wrong data"
)
}
*
result
.
(
*
hexutil
.
Bytes
)
=
signature
return
nil
},
},
func
(
signature
,
data
[]
byte
)
(
*
ecdsa
.
PublicKey
,
error
)
{
return
publicKey
,
nil
})
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
s
,
err
:=
signer
.
SignTypedData
(
typedData
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
s
,
signature
)
{
t
.
Fatalf
(
"wrong signature. wanted %x, got %x"
,
signature
,
s
)
}
}
pkg/crypto/eip712/typeddata.go
0 → 100644
View file @
22d7e53b
// Copyright 2020 The Swarm 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
eip712
import
(
"fmt"
"github.com/ethereum/go-ethereum/signer/core"
)
// type aliases to avoid importing "core" everywhere
type
TypedData
=
core
.
TypedData
type
TypedDataDomain
=
core
.
TypedDataDomain
type
Types
=
core
.
Types
type
Type
=
core
.
Type
type
TypedDataMessage
=
core
.
TypedDataMessage
// EncodeForSigning encodes the hash that will be signed for the given EIP712 data
func
EncodeForSigning
(
typedData
*
TypedData
)
([]
byte
,
error
)
{
domainSeparator
,
err
:=
typedData
.
HashStruct
(
"EIP712Domain"
,
typedData
.
Domain
.
Map
())
if
err
!=
nil
{
return
nil
,
err
}
typedDataHash
,
err
:=
typedData
.
HashStruct
(
typedData
.
PrimaryType
,
typedData
.
Message
)
if
err
!=
nil
{
return
nil
,
err
}
rawData
:=
[]
byte
(
fmt
.
Sprintf
(
"
\x19\x01
%s%s"
,
string
(
domainSeparator
),
string
(
typedDataHash
)))
return
rawData
,
nil
}
// EIP712DomainType is the type description for the EIP712 Domain
var
EIP712DomainType
=
[]
Type
{
{
Name
:
"name"
,
Type
:
"string"
,
},
{
Name
:
"version"
,
Type
:
"string"
,
},
{
Name
:
"chainId"
,
Type
:
"uint256"
,
},
}
pkg/crypto/signer.go
View file @
22d7e53b
...
...
@@ -12,6 +12,7 @@ import (
"github.com/btcsuite/btcd/btcec"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/crypto/eip712"
)
var
(
...
...
@@ -19,28 +20,30 @@ var (
)
type
Signer
interface
{
// Sign signs data with ethereum prefix (eip191 type 0x45)
// Sign signs data with ethereum prefix (eip191 type 0x45)
.
Sign
(
data
[]
byte
)
([]
byte
,
error
)
// SignTx signs an ethereum transaction
// SignTx signs an ethereum transaction
.
SignTx
(
transaction
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
// PublicKey returns the public key this signer uses
// SignTypedData signs data according to eip712.
SignTypedData
(
typedData
*
eip712
.
TypedData
)
([]
byte
,
error
)
// PublicKey returns the public key this signer uses.
PublicKey
()
(
*
ecdsa
.
PublicKey
,
error
)
// EthereumAddress returns the ethereum address this signer uses
// EthereumAddress returns the ethereum address this signer uses
.
EthereumAddress
()
(
common
.
Address
,
error
)
}
// addEthereumPrefix adds the ethereum prefix to the data
// addEthereumPrefix adds the ethereum prefix to the data
.
func
addEthereumPrefix
(
data
[]
byte
)
[]
byte
{
return
[]
byte
(
fmt
.
Sprintf
(
"
\x19
Ethereum Signed Message:
\n
%d%s"
,
len
(
data
),
data
))
}
// hashWithEthereumPrefix returns the hash that should be signed for the given data
// hashWithEthereumPrefix returns the hash that should be signed for the given data
.
func
hashWithEthereumPrefix
(
data
[]
byte
)
([]
byte
,
error
)
{
return
LegacyKeccak256
(
addEthereumPrefix
(
data
))
}
// Recover verifies signature with the data base provided.
// It is using `btcec.RecoverCompact` function
// It is using `btcec.RecoverCompact` function
.
func
Recover
(
signature
,
data
[]
byte
)
(
*
ecdsa
.
PublicKey
,
error
)
{
if
len
(
signature
)
!=
65
{
return
nil
,
ErrInvalidLength
...
...
@@ -69,48 +72,36 @@ func NewDefaultSigner(key *ecdsa.PrivateKey) Signer {
}
}
// PublicKey returns the public key this signer uses
// PublicKey returns the public key this signer uses
.
func
(
d
*
defaultSigner
)
PublicKey
()
(
*
ecdsa
.
PublicKey
,
error
)
{
return
&
d
.
key
.
PublicKey
,
nil
}
// Sign signs data with ethereum prefix (eip191 type 0x45)
// Sign signs data with ethereum prefix (eip191 type 0x45)
.
func
(
d
*
defaultSigner
)
Sign
(
data
[]
byte
)
(
signature
[]
byte
,
err
error
)
{
hash
,
err
:=
hashWithEthereumPrefix
(
data
)
if
err
!=
nil
{
return
nil
,
err
}
signature
,
err
=
btcec
.
SignCompact
(
btcec
.
S256
(),
(
*
btcec
.
PrivateKey
)(
d
.
key
),
hash
,
true
)
if
err
!=
nil
{
return
nil
,
err
}
// Convert to Ethereum signature format with 'recovery id' v at the end.
v
:=
signature
[
0
]
copy
(
signature
,
signature
[
1
:
])
signature
[
64
]
=
v
return
signature
,
nil
return
d
.
sign
(
hash
,
true
)
}
// SignTx signs an ethereum transaction
// SignTx signs an ethereum transaction
.
func
(
d
*
defaultSigner
)
SignTx
(
transaction
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
{
hash
:=
(
&
types
.
HomesteadSigner
{})
.
Hash
(
transaction
)
.
Bytes
()
// isCompressedKey is false here so we get the expected v value (27 or 28)
signature
,
err
:=
btcec
.
SignCompact
(
btcec
.
S256
(),
(
*
btcec
.
PrivateKey
)(
d
.
key
),
hash
,
false
)
signature
,
err
:=
d
.
sign
(
hash
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
// Convert to Ethereum signature format with 'recovery id' v at the end.
v
:=
signature
[
0
]
copy
(
signature
,
signature
[
1
:
])
// v value needs to be adjusted by 27 as transaction.WithSignature expects it to be 0 or 1
signature
[
64
]
=
v
-
27
signature
[
64
]
-=
27
return
transaction
.
WithSignature
(
&
types
.
HomesteadSigner
{},
signature
)
}
// EthereumAddress returns the ethereum address this signer uses
// EthereumAddress returns the ethereum address this signer uses
.
func
(
d
*
defaultSigner
)
EthereumAddress
()
(
common
.
Address
,
error
)
{
publicKey
,
err
:=
d
.
PublicKey
()
if
err
!=
nil
{
...
...
@@ -124,3 +115,56 @@ func (d *defaultSigner) EthereumAddress() (common.Address, error) {
copy
(
ethAddress
[
:
],
eth
)
return
ethAddress
,
nil
}
// SignTypedData signs data according to eip712.
func
(
d
*
defaultSigner
)
SignTypedData
(
typedData
*
eip712
.
TypedData
)
([]
byte
,
error
)
{
rawData
,
err
:=
eip712
.
EncodeForSigning
(
typedData
)
if
err
!=
nil
{
return
nil
,
err
}
sighash
,
err
:=
LegacyKeccak256
(
rawData
)
if
err
!=
nil
{
return
nil
,
err
}
return
d
.
sign
(
sighash
,
false
)
}
// sign the provided hash and convert it to the ethereum (r,s,v) format.
func
(
d
*
defaultSigner
)
sign
(
sighash
[]
byte
,
isCompressedKey
bool
)
([]
byte
,
error
)
{
signature
,
err
:=
btcec
.
SignCompact
(
btcec
.
S256
(),
(
*
btcec
.
PrivateKey
)(
d
.
key
),
sighash
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
// Convert to Ethereum signature format with 'recovery id' v at the end.
v
:=
signature
[
0
]
copy
(
signature
,
signature
[
1
:
])
signature
[
64
]
=
v
return
signature
,
nil
}
// RecoverEIP712 recovers the public key for eip712 signed data.
func
RecoverEIP712
(
signature
[]
byte
,
data
*
eip712
.
TypedData
)
(
*
ecdsa
.
PublicKey
,
error
)
{
if
len
(
signature
)
!=
65
{
return
nil
,
errors
.
New
(
"invalid length"
)
}
// Convert to btcec input format with 'recovery id' v at the beginning.
btcsig
:=
make
([]
byte
,
65
)
btcsig
[
0
]
=
signature
[
64
]
copy
(
btcsig
[
1
:
],
signature
)
rawData
,
err
:=
eip712
.
EncodeForSigning
(
data
)
if
err
!=
nil
{
return
nil
,
err
}
sighash
,
err
:=
LegacyKeccak256
(
rawData
)
if
err
!=
nil
{
return
nil
,
err
}
p
,
_
,
err
:=
btcec
.
RecoverCompact
(
btcec
.
S256
(),
btcsig
,
sighash
)
return
(
*
ecdsa
.
PublicKey
)(
p
),
err
}
pkg/crypto/signer_test.go
View file @
22d7e53b
...
...
@@ -5,6 +5,7 @@
package
crypto_test
import
(
"bytes"
"encoding/hex"
"errors"
"math/big"
...
...
@@ -14,6 +15,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/crypto/eip712"
)
func
TestDefaultSigner
(
t
*
testing
.
T
)
{
...
...
@@ -122,3 +124,90 @@ func TestDefaultSignerSignTx(t *testing.T) {
t
.
Fatalf
(
"wrong s value. expected %x, got %x"
,
expectedS
,
s
)
}
}
var
testTypedData
=
&
eip712
.
TypedData
{
Domain
:
eip712
.
TypedDataDomain
{
Name
:
"test"
,
Version
:
"1.0"
,
},
Types
:
eip712
.
Types
{
"EIP712Domain"
:
{
{
Name
:
"name"
,
Type
:
"string"
,
},
{
Name
:
"version"
,
Type
:
"string"
,
},
},
"MyType"
:
{
{
Name
:
"test"
,
Type
:
"string"
,
},
},
},
Message
:
eip712
.
TypedDataMessage
{
"test"
:
"abc"
,
},
PrimaryType
:
"MyType"
,
}
func
TestDefaultSignerTypedData
(
t
*
testing
.
T
)
{
data
,
err
:=
hex
.
DecodeString
(
"634fb5a872396d9693e5c9f9d7233cfa93f395c093371017ff44aa9ae6564cdd"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
privKey
,
err
:=
crypto
.
DecodeSecp256k1PrivateKey
(
data
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
sig
,
err
:=
signer
.
SignTypedData
(
testTypedData
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expected
,
err
:=
hex
.
DecodeString
(
"60f054c45d37a0359d4935da0454bc19f02a8c01ceee8a112cfe48c8e2357b842e897f76389fb96947c6d2c80cbfe081052204e7b0c3cc1194a973a09b1614f71c"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
expected
,
sig
)
{
t
.
Fatalf
(
"wrong signature. expected %x, got %x"
,
expected
,
sig
)
}
}
func
TestRecoverEIP712
(
t
*
testing
.
T
)
{
data
,
err
:=
hex
.
DecodeString
(
"634fb5a872396d9693e5c9f9d7233cfa93f395c093371017ff44aa9ae6564cdd"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
privKey
,
err
:=
crypto
.
DecodeSecp256k1PrivateKey
(
data
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expected
,
err
:=
hex
.
DecodeString
(
"60f054c45d37a0359d4935da0454bc19f02a8c01ceee8a112cfe48c8e2357b842e897f76389fb96947c6d2c80cbfe081052204e7b0c3cc1194a973a09b1614f71c"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
pubKey
,
err
:=
crypto
.
RecoverEIP712
(
expected
,
testTypedData
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
privKey
.
PublicKey
.
X
.
Cmp
(
pubKey
.
X
)
!=
0
{
t
.
Fatalf
(
"recovered wrong public key. wanted %x, got %x"
,
privKey
.
PublicKey
,
pubKey
)
}
if
privKey
.
PublicKey
.
Y
.
Cmp
(
pubKey
.
Y
)
!=
0
{
t
.
Fatalf
(
"recovered wrong public key. wanted %x, got %x"
,
privKey
.
PublicKey
,
pubKey
)
}
}
pkg/node/node.go
View file @
22d7e53b
...
...
@@ -165,6 +165,11 @@ func NewBee(addr string, swarmAddress swarm.Address, keystore keystore.Service,
// print ethereum address so users know which address we need to fund
logger
.
Infof
(
"using ethereum address %x"
,
overlayEthAddress
)
chainId
,
err
:=
swapBackend
.
ChainID
(
p2pCtx
)
if
err
!=
nil
{
return
nil
,
err
}
// TODO: factory address discovery for well-known networks (goerli for beta)
if
o
.
SwapFactoryAddress
==
""
{
...
...
@@ -178,6 +183,8 @@ func NewBee(addr string, swarmAddress swarm.Address, keystore keystore.Service,
return
nil
,
err
}
chequeSigner
:=
chequebook
.
NewChequeSigner
(
signer
,
chainId
.
Int64
())
// initialize chequebook logic
// return value is ignored because we don't do anything yet after initialization. this will be passed into swap settlement.
chequebookService
,
err
=
chequebook
.
Init
(
p2pCtx
,
...
...
@@ -188,6 +195,7 @@ func NewBee(addr string, swarmAddress swarm.Address, keystore keystore.Service,
transactionService
,
swapBackend
,
overlayEthAddress
,
chequeSigner
,
chequebook
.
NewSimpleSwapBindings
,
chequebook
.
NewERC20Bindings
)
if
err
!=
nil
{
...
...
pkg/settlement/swap/chequebook/cheque.go
0 → 100644
View file @
22d7e53b
// Copyright 2020 The Swarm 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
(
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/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
,
s
.
chainID
))
}
func
(
cheque
*
Cheque
)
String
()
string
{
return
fmt
.
Sprintf
(
"Contract: %x Beneficiary: %x CumulativePayout: %v"
,
cheque
.
Chequebook
,
cheque
.
Beneficiary
,
cheque
.
CumulativePayout
)
}
pkg/settlement/swap/chequebook/cheque_test.go
0 → 100644
View file @
22d7e53b
// Copyright 2020 The Swarm 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_test
import
(
"bytes"
"encoding/hex"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/crypto/eip712"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
)
func
TestSignCheque
(
t
*
testing
.
T
)
{
chequebookAddress
:=
common
.
HexToAddress
(
"0x8d3766440f0d7b949a5e32995d09619a7f86e632"
)
beneficiaryAddress
:=
common
.
HexToAddress
(
"0xb8d424e9662fe0837fb1d728f1ac97cebb1085fe"
)
signature
:=
common
.
Hex2Bytes
(
"abcd"
)
cumulativePayout
:=
big
.
NewInt
(
10
)
chainId
:=
int64
(
1
)
cheque
:=
&
chequebook
.
Cheque
{
Chequebook
:
chequebookAddress
,
Beneficiary
:
beneficiaryAddress
,
CumulativePayout
:
cumulativePayout
,
}
signer
:=
&
signerMock
{
signTypedData
:
func
(
data
*
eip712
.
TypedData
)
([]
byte
,
error
)
{
if
data
.
Message
[
"beneficiary"
]
.
(
string
)
!=
beneficiaryAddress
.
Hex
()
{
t
.
Fatal
(
"signing cheque with wrong beneficiary"
)
}
if
data
.
Message
[
"chequebook"
]
.
(
string
)
!=
chequebookAddress
.
Hex
()
{
t
.
Fatal
(
"signing cheque for wrong chequebook"
)
}
if
data
.
Message
[
"cumulativePayout"
]
.
(
string
)
!=
cumulativePayout
.
String
()
{
t
.
Fatal
(
"signing cheque with wrong cumulativePayout"
)
}
return
signature
,
nil
},
}
chequeSigner
:=
chequebook
.
NewChequeSigner
(
signer
,
chainId
)
result
,
err
:=
chequeSigner
.
Sign
(
cheque
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
result
,
signature
)
{
t
.
Fatalf
(
"returned wrong signature. wanted %x, got %x"
,
signature
,
result
)
}
}
func
TestSignChequeIntegration
(
t
*
testing
.
T
)
{
chequebookAddress
:=
common
.
HexToAddress
(
"0xfa02D396842E6e1D319E8E3D4D870338F791AA25"
)
beneficiaryAddress
:=
common
.
HexToAddress
(
"0x98E6C644aFeB94BBfB9FF60EB26fc9D83BBEcA79"
)
cumulativePayout
:=
big
.
NewInt
(
500
)
chainId
:=
int64
(
1
)
data
,
err
:=
hex
.
DecodeString
(
"634fb5a872396d9693e5c9f9d7233cfa93f395c093371017ff44aa9ae6564cdd"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
privKey
,
err
:=
crypto
.
DecodeSecp256k1PrivateKey
(
data
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
cheque
:=
&
chequebook
.
Cheque
{
Chequebook
:
chequebookAddress
,
Beneficiary
:
beneficiaryAddress
,
CumulativePayout
:
cumulativePayout
,
}
chequeSigner
:=
chequebook
.
NewChequeSigner
(
signer
,
chainId
)
result
,
err
:=
chequeSigner
.
Sign
(
cheque
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// computed using ganache
expectedSignature
,
err
:=
hex
.
DecodeString
(
"171b63fc598ae2c7987f4a756959dadddd84ccd2071e7b5c3aa3437357be47286125edc370c344a163ba7f4183dfd3611996274a13e4b3496610fc00c0e2fc421c"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
result
,
expectedSignature
)
{
t
.
Fatalf
(
"returned wrong signature. wanted %x, got %x"
,
expectedSignature
,
result
)
}
}
pkg/settlement/swap/chequebook/chequebook.go
View file @
22d7e53b
...
...
@@ -7,25 +7,29 @@ package chequebook
import
(
"context"
"errors"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/sw3-bindings/v2/simpleswapfactory"
)
// Service is the main interface for interacting with the nodes chequebook
// Service is the main interface for interacting with the nodes chequebook
.
type
Service
interface
{
// Deposit starts depositing erc20 token into the chequebook. This returns once the transactions has been broadcast.
Deposit
(
ctx
context
.
Context
,
amount
*
big
.
Int
)
(
hash
common
.
Hash
,
err
error
)
// WaitForDeposit waits for the deposit transaction to confirm and verifies the result
// WaitForDeposit waits for the deposit transaction to confirm and verifies the result
.
WaitForDeposit
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
error
// Balance returns the token balance of the chequebook
// Balance returns the token balance of the chequebook
.
Balance
(
ctx
context
.
Context
)
(
*
big
.
Int
,
error
)
// Address returns the address of the used chequebook contract
// Address returns the address of the used chequebook contract
.
Address
()
common
.
Address
// Issue a new cheque for the beneficiary with an cumulativePayout amount higher than the last.
Issue
(
beneficiary
common
.
Address
,
amount
*
big
.
Int
)
(
*
SignedCheque
,
error
)
}
type
service
struct
{
...
...
@@ -40,10 +44,13 @@ type service struct {
erc20Address
common
.
Address
erc20ABI
abi
.
ABI
erc20Instance
ERC20Binding
store
storage
.
StateStorer
chequeSigner
ChequeSigner
}
// New creates a new chequebook service for the provided chequebook contract
func
New
(
backend
Backend
,
transactionService
TransactionService
,
address
,
erc20Address
,
ownerAddress
common
.
Address
,
simpleSwapBindingFunc
SimpleSwapBindingFunc
,
erc20BindingFunc
ERC20BindingFunc
)
(
Service
,
error
)
{
// New creates a new chequebook service for the provided chequebook contract
.
func
New
(
backend
Backend
,
transactionService
TransactionService
,
address
,
erc20Address
,
ownerAddress
common
.
Address
,
s
tore
storage
.
StateStorer
,
chequeSigner
ChequeSigner
,
s
impleSwapBindingFunc
SimpleSwapBindingFunc
,
erc20BindingFunc
ERC20BindingFunc
)
(
Service
,
error
)
{
chequebookABI
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
simpleswapfactory
.
ERC20SimpleSwapABI
))
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -74,10 +81,12 @@ func New(backend Backend, transactionService TransactionService, address, erc20A
erc20Address
:
erc20Address
,
erc20ABI
:
erc20ABI
,
erc20Instance
:
erc20Instance
,
store
:
store
,
chequeSigner
:
chequeSigner
,
},
nil
}
// Address returns the address of the used chequebook contract
// Address returns the address of the used chequebook contract
.
func
(
s
*
service
)
Address
()
common
.
Address
{
return
s
.
address
}
...
...
@@ -117,14 +126,14 @@ func (s *service) Deposit(ctx context.Context, amount *big.Int) (hash common.Has
return
txHash
,
nil
}
// Balance returns the token balance of the chequebook
// Balance returns the token balance of the chequebook
.
func
(
s
*
service
)
Balance
(
ctx
context
.
Context
)
(
*
big
.
Int
,
error
)
{
return
s
.
chequebookInstance
.
Balance
(
&
bind
.
CallOpts
{
Context
:
ctx
,
})
}
// WaitForDeposit waits for the deposit transaction to confirm and verifies the result
// WaitForDeposit waits for the deposit transaction to confirm and verifies the result
.
func
(
s
*
service
)
WaitForDeposit
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
error
{
receipt
,
err
:=
s
.
transactionService
.
WaitForReceipt
(
ctx
,
txHash
)
if
err
!=
nil
{
...
...
@@ -135,3 +144,44 @@ func (s *service) WaitForDeposit(ctx context.Context, txHash common.Hash) error
}
return
nil
}
// Issue issues a new cheque.
func
(
s
*
service
)
Issue
(
beneficiary
common
.
Address
,
amount
*
big
.
Int
)
(
*
SignedCheque
,
error
)
{
storeKey
:=
fmt
.
Sprintf
(
"chequebook_last_issued_cheque_%x"
,
beneficiary
)
var
cumulativePayout
*
big
.
Int
var
lastCheque
Cheque
err
:=
s
.
store
.
Get
(
storeKey
,
&
lastCheque
)
if
err
!=
nil
{
if
err
!=
storage
.
ErrNotFound
{
return
nil
,
err
}
cumulativePayout
=
big
.
NewInt
(
0
)
}
else
{
cumulativePayout
=
lastCheque
.
CumulativePayout
}
// increase cumulativePayout by amount
cumulativePayout
=
cumulativePayout
.
Add
(
cumulativePayout
,
amount
)
cheque
:=
Cheque
{
Chequebook
:
s
.
address
,
CumulativePayout
:
cumulativePayout
,
Beneficiary
:
beneficiary
,
}
sig
,
err
:=
s
.
chequeSigner
.
Sign
(
&
cheque
)
if
err
!=
nil
{
return
nil
,
err
}
err
=
s
.
store
.
Put
(
storeKey
,
cheque
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
SignedCheque
{
Cheque
:
cheque
,
Signature
:
sig
,
},
nil
}
pkg/settlement/swap/chequebook/chequebook_test.go
View file @
22d7e53b
...
...
@@ -31,6 +31,8 @@ func newTestChequebook(
address
,
erc20address
,
ownerAdress
,
nil
,
nil
,
func
(
addr
common
.
Address
,
b
bind
.
ContractBackend
)
(
chequebook
.
SimpleSwapBinding
,
error
)
{
if
addr
!=
address
{
t
.
Fatalf
(
"initialised binding with wrong address. wanted %x, got %x"
,
address
,
addr
)
...
...
pkg/settlement/swap/chequebook/common_test.go
View file @
22d7e53b
...
...
@@ -6,12 +6,14 @@ package chequebook_test
import
(
"context"
"crypto/ecdsa"
"math/big"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/crypto/eip712"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
"github.com/ethersphere/sw3-bindings/v2/simpleswapfactory"
)
...
...
@@ -103,6 +105,10 @@ func (m *simpleSwapBindingMock) Balance(o *bind.CallOpts) (*big.Int, error) {
return
m
.
balance
(
o
)
}
func
(
m
*
simpleSwapBindingMock
)
Issuer
(
*
bind
.
CallOpts
)
(
common
.
Address
,
error
)
{
return
common
.
Address
{},
nil
}
type
erc20BindingMock
struct
{
balanceOf
func
(
*
bind
.
CallOpts
,
common
.
Address
)
(
*
big
.
Int
,
error
)
}
...
...
@@ -110,3 +116,28 @@ type erc20BindingMock struct {
func
(
m
*
erc20BindingMock
)
BalanceOf
(
o
*
bind
.
CallOpts
,
a
common
.
Address
)
(
*
big
.
Int
,
error
)
{
return
m
.
balanceOf
(
o
,
a
)
}
type
signerMock
struct
{
signTx
func
(
transaction
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
signTypedData
func
(
*
eip712
.
TypedData
)
([]
byte
,
error
)
}
func
(
*
signerMock
)
EthereumAddress
()
(
common
.
Address
,
error
)
{
return
common
.
Address
{},
nil
}
func
(
*
signerMock
)
Sign
(
data
[]
byte
)
([]
byte
,
error
)
{
return
nil
,
nil
}
func
(
m
*
signerMock
)
SignTx
(
transaction
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
{
return
m
.
signTx
(
transaction
)
}
func
(
*
signerMock
)
PublicKey
()
(
*
ecdsa
.
PublicKey
,
error
)
{
return
nil
,
nil
}
func
(
m
*
signerMock
)
SignTypedData
(
d
*
eip712
.
TypedData
)
([]
byte
,
error
)
{
return
m
.
signTypedData
(
d
)
}
pkg/settlement/swap/chequebook/factory.go
View file @
22d7e53b
...
...
@@ -23,15 +23,15 @@ var (
ErrNotDeployedByFactory
=
errors
.
New
(
"chequebook not deployed by factory"
)
)
// Factory is the main interface for interacting with the chequebook factory
// Factory is the main interface for interacting with the chequebook factory
.
type
Factory
interface
{
// ERC20Address returns the token for which this factory deploys chequebooks
// ERC20Address returns the token for which this factory deploys chequebooks
.
ERC20Address
(
ctx
context
.
Context
)
(
common
.
Address
,
error
)
// Deploy deploys a new chequebook and returns once confirmed
// Deploy deploys a new chequebook and returns once confirmed
.
Deploy
(
ctx
context
.
Context
,
issuer
common
.
Address
,
defaultHardDepositTimeoutDuration
*
big
.
Int
)
(
common
.
Address
,
error
)
// VerifyBytecode checks that the factory is valid
// VerifyBytecode checks that the factory is valid
.
VerifyBytecode
(
ctx
context
.
Context
)
error
// VerifyChequebook checks that the supplied chequebook has been deployed by this factory
// VerifyChequebook checks that the supplied chequebook has been deployed by this factory
.
VerifyChequebook
(
ctx
context
.
Context
,
chequebook
common
.
Address
)
error
}
...
...
@@ -44,7 +44,7 @@ type factory struct {
instance
SimpleSwapFactoryBinding
}
// NewFactory creates a new factory service for the provided factory contract
// NewFactory creates a new factory service for the provided factory contract
.
func
NewFactory
(
backend
Backend
,
transactionService
TransactionService
,
address
common
.
Address
,
simpleSwapFactoryBindingFunc
SimpleSwapFactoryBindingFunc
)
(
Factory
,
error
)
{
ABI
,
err
:=
abi
.
JSON
(
strings
.
NewReader
(
simpleswapfactory
.
SimpleSwapFactoryABI
))
if
err
!=
nil
{
...
...
@@ -65,7 +65,7 @@ func NewFactory(backend Backend, transactionService TransactionService, address
},
nil
}
// Deploy deploys a new chequebook and returns once confirmed
// Deploy deploys a new chequebook and returns once confirmed
.
func
(
c
*
factory
)
Deploy
(
ctx
context
.
Context
,
issuer
common
.
Address
,
defaultHardDepositTimeoutDuration
*
big
.
Int
)
(
common
.
Address
,
error
)
{
callData
,
err
:=
c
.
ABI
.
Pack
(
"deploySimpleSwap"
,
issuer
,
big
.
NewInt
(
0
)
.
Set
(
defaultHardDepositTimeoutDuration
))
if
err
!=
nil
{
...
...
@@ -98,7 +98,7 @@ func (c *factory) Deploy(ctx context.Context, issuer common.Address, defaultHard
return
chequebookAddress
,
nil
}
// parseDeployReceipt parses the address of the deployed chequebook from the receipt
// parseDeployReceipt parses the address of the deployed chequebook from the receipt
.
func
(
c
*
factory
)
parseDeployReceipt
(
receipt
*
types
.
Receipt
)
(
address
common
.
Address
,
err
error
)
{
if
receipt
.
Status
!=
1
{
return
common
.
Address
{},
ErrTransactionReverted
...
...
@@ -118,7 +118,7 @@ func (c *factory) parseDeployReceipt(receipt *types.Receipt) (address common.Add
return
address
,
nil
}
// VerifyBytecode checks that the factory is valid
// VerifyBytecode checks that the factory is valid
.
func
(
c
*
factory
)
VerifyBytecode
(
ctx
context
.
Context
)
(
err
error
)
{
code
,
err
:=
c
.
backend
.
CodeAt
(
ctx
,
c
.
address
,
nil
)
if
err
!=
nil
{
...
...
@@ -132,7 +132,7 @@ func (c *factory) VerifyBytecode(ctx context.Context) (err error) {
return
nil
}
// VerifyChequebook checks that the supplied chequebook has been deployed by this factory
// VerifyChequebook checks that the supplied chequebook has been deployed by this factory
.
func
(
c
*
factory
)
VerifyChequebook
(
ctx
context
.
Context
,
chequebook
common
.
Address
)
error
{
deployed
,
err
:=
c
.
instance
.
DeployedContracts
(
&
bind
.
CallOpts
{
Context
:
ctx
,
...
...
@@ -146,7 +146,7 @@ func (c *factory) VerifyChequebook(ctx context.Context, chequebook common.Addres
return
nil
}
// ERC20Address returns the token for which this factory deploys chequebooks
// ERC20Address returns the token for which this factory deploys chequebooks
.
func
(
c
*
factory
)
ERC20Address
(
ctx
context
.
Context
)
(
common
.
Address
,
error
)
{
erc20Address
,
err
:=
c
.
instance
.
ERC20Address
(
&
bind
.
CallOpts
{
Context
:
ctx
,
...
...
pkg/settlement/swap/chequebook/init.go
View file @
22d7e53b
...
...
@@ -15,7 +15,7 @@ import (
const
chequebookKey
=
"chequebook"
// Init initialises the chequebook service
// Init initialises the chequebook service
.
func
Init
(
ctx
context
.
Context
,
chequebookFactory
Factory
,
...
...
@@ -25,6 +25,7 @@ func Init(
transactionService
TransactionService
,
swapBackend
Backend
,
overlayEthAddress
common
.
Address
,
chequeSigner
ChequeSigner
,
simpleSwapBindingFunc
SimpleSwapBindingFunc
,
erc20BindingFunc
ERC20BindingFunc
)
(
chequebookService
Service
,
err
error
)
{
// verify that the supplied factory is valid
...
...
@@ -60,7 +61,7 @@ func Init(
return
nil
,
err
}
chequebookService
,
err
=
New
(
swapBackend
,
transactionService
,
chequebookAddress
,
erc20Address
,
overlayEthAddress
,
simpleSwapBindingFunc
,
erc20BindingFunc
)
chequebookService
,
err
=
New
(
swapBackend
,
transactionService
,
chequebookAddress
,
erc20Address
,
overlayEthAddress
,
s
tateStore
,
chequeSigner
,
s
impleSwapBindingFunc
,
erc20BindingFunc
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -81,7 +82,7 @@ func Init(
logger
.
Infof
(
"deposited to chequebook %x in transaction %x"
,
chequebookAddress
,
depositHash
)
}
}
else
{
chequebookService
,
err
=
New
(
swapBackend
,
transactionService
,
chequebookAddress
,
erc20Address
,
overlayEthAddress
,
simpleSwapBindingFunc
,
erc20BindingFunc
)
chequebookService
,
err
=
New
(
swapBackend
,
transactionService
,
chequebookAddress
,
erc20Address
,
overlayEthAddress
,
s
tateStore
,
chequeSigner
,
s
impleSwapBindingFunc
,
erc20BindingFunc
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
pkg/settlement/swap/chequebook/mock/chequebook.go
View file @
22d7e53b
...
...
@@ -67,6 +67,10 @@ func (s *Service) Address() common.Address {
return
common
.
Address
{}
}
func
(
s
*
Service
)
Issue
(
beneficiary
common
.
Address
,
amount
*
big
.
Int
)
(
*
chequebook
.
SignedCheque
,
error
)
{
return
nil
,
errors
.
New
(
"Error"
)
}
// Option is the option passed to the mock Chequebook service
type
Option
interface
{
apply
(
*
Service
)
...
...
pkg/settlement/swap/chequebook/transaction.go
View file @
22d7e53b
...
...
@@ -22,13 +22,13 @@ var (
ErrTransactionReverted
=
errors
.
New
(
"transaction reverted"
)
)
// Backend is the minimum of blockchain backend functions we need
// Backend is the minimum of blockchain backend functions we need
.
type
Backend
interface
{
bind
.
ContractBackend
TransactionReceipt
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
*
types
.
Receipt
,
error
)
}
// TxRequest describes a request for a transaction that can be executed
// TxRequest describes a request for a transaction that can be executed
.
type
TxRequest
struct
{
To
common
.
Address
// recipient of the transaction
Data
[]
byte
// transaction data
...
...
@@ -39,9 +39,9 @@ type TxRequest struct {
// TransactionService is the service to send transactions. It takes care of gas price, gas limit and nonce management.
type
TransactionService
interface
{
// Send creates a transaction based on the request and sends it
// Send creates a transaction based on the request and sends it
.
Send
(
ctx
context
.
Context
,
request
*
TxRequest
)
(
txHash
common
.
Hash
,
err
error
)
// WaitForReceipt waits until either the transaction with the given hash has been mined or the context is cancelled
// WaitForReceipt waits until either the transaction with the given hash has been mined or the context is cancelled
.
WaitForReceipt
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
receipt
*
types
.
Receipt
,
err
error
)
}
...
...
@@ -52,7 +52,7 @@ type transactionService struct {
sender
common
.
Address
}
// NewTransactionService creates a new transaction service
// NewTransactionService creates a new transaction service
.
func
NewTransactionService
(
logger
logging
.
Logger
,
backend
Backend
,
signer
crypto
.
Signer
)
(
TransactionService
,
error
)
{
senderAddress
,
err
:=
signer
.
EthereumAddress
()
if
err
!=
nil
{
...
...
@@ -66,7 +66,7 @@ func NewTransactionService(logger logging.Logger, backend Backend, signer crypto
},
nil
}
// Send creates and signs a transaction based on the request and sends it
// Send creates and signs a transaction based on the request and sends it
.
func
(
t
*
transactionService
)
Send
(
ctx
context
.
Context
,
request
*
TxRequest
)
(
txHash
common
.
Hash
,
err
error
)
{
tx
,
err
:=
prepareTransaction
(
ctx
,
request
,
t
.
sender
,
t
.
backend
)
if
err
!=
nil
{
...
...
@@ -86,7 +86,7 @@ func (t *transactionService) Send(ctx context.Context, request *TxRequest) (txHa
return
signedTx
.
Hash
(),
nil
}
// WaitForReceipt waits until either the transaction with the given hash has been mined or the context is cancelled
// WaitForReceipt waits until either the transaction with the given hash has been mined or the context is cancelled
.
func
(
t
*
transactionService
)
WaitForReceipt
(
ctx
context
.
Context
,
txHash
common
.
Hash
)
(
receipt
*
types
.
Receipt
,
err
error
)
{
for
{
receipt
,
err
:=
t
.
backend
.
TransactionReceipt
(
ctx
,
txHash
)
...
...
@@ -108,7 +108,7 @@ func (t *transactionService) WaitForReceipt(ctx context.Context, txHash common.H
}
}
// prepareTransaction creates a signable transaction based on a request
// prepareTransaction creates a signable transaction based on a request
.
func
prepareTransaction
(
ctx
context
.
Context
,
request
*
TxRequest
,
from
common
.
Address
,
backend
Backend
)
(
tx
*
types
.
Transaction
,
err
error
)
{
var
gasLimit
uint64
if
request
.
GasLimit
==
0
{
...
...
pkg/settlement/swap/chequebook/transaction_test.go
View file @
22d7e53b
...
...
@@ -7,7 +7,6 @@ package chequebook_test
import
(
"bytes"
"context"
"crypto/ecdsa"
"io/ioutil"
"math/big"
"testing"
...
...
@@ -19,24 +18,6 @@ import (
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
)
type
signerMock
struct
{
signTx
func
(
transaction
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
}
func
(
*
signerMock
)
EthereumAddress
()
(
common
.
Address
,
error
)
{
return
common
.
Address
{},
nil
}
func
(
*
signerMock
)
Sign
(
data
[]
byte
)
([]
byte
,
error
)
{
return
nil
,
nil
}
func
(
m
*
signerMock
)
SignTx
(
transaction
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
{
return
m
.
signTx
(
transaction
)
}
func
(
*
signerMock
)
PublicKey
()
(
*
ecdsa
.
PublicKey
,
error
)
{
return
nil
,
nil
}
func
TestTransactionSend
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
recipient
:=
common
.
HexToAddress
(
"0xabcd"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment