Commit d1920d8f authored by Ralph Pichler's avatar Ralph Pichler Committed by GitHub

use eip155 signing in in-memory signer (#1338)

parent 4e05c8ad
...@@ -109,7 +109,7 @@ func (c *clefSigner) Sign(data []byte) ([]byte, error) { ...@@ -109,7 +109,7 @@ func (c *clefSigner) Sign(data []byte) ([]byte, error) {
} }
// SignTx signs an ethereum transaction. // SignTx signs an ethereum transaction.
func (c *clefSigner) SignTx(transaction *types.Transaction) (*types.Transaction, error) { func (c *clefSigner) SignTx(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
// chainId is nil here because it is set on the clef side // chainId is nil here because it is set on the clef side
return c.clef.SignTx(c.account, transaction, nil) return c.clef.SignTx(c.account, transaction, nil)
} }
......
...@@ -6,6 +6,7 @@ package mock ...@@ -6,6 +6,7 @@ package mock
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -14,7 +15,7 @@ import ( ...@@ -14,7 +15,7 @@ import (
) )
type signerMock struct { type signerMock struct {
signTx func(transaction *types.Transaction) (*types.Transaction, error) signTx func(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error)
signTypedData func(*eip712.TypedData) ([]byte, error) signTypedData func(*eip712.TypedData) ([]byte, error)
ethereumAddress func() (common.Address, error) ethereumAddress func() (common.Address, error)
} }
...@@ -30,8 +31,8 @@ func (*signerMock) Sign(data []byte) ([]byte, error) { ...@@ -30,8 +31,8 @@ func (*signerMock) Sign(data []byte) ([]byte, error) {
return nil, nil return nil, nil
} }
func (m *signerMock) SignTx(transaction *types.Transaction) (*types.Transaction, error) { func (m *signerMock) SignTx(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
return m.signTx(transaction) return m.signTx(transaction, chainID)
} }
func (*signerMock) PublicKey() (*ecdsa.PublicKey, error) { func (*signerMock) PublicKey() (*ecdsa.PublicKey, error) {
...@@ -59,7 +60,7 @@ type optionFunc func(*signerMock) ...@@ -59,7 +60,7 @@ type optionFunc func(*signerMock)
func (f optionFunc) apply(r *signerMock) { f(r) } func (f optionFunc) apply(r *signerMock) { f(r) }
func WithSignTxFunc(f func(transaction *types.Transaction) (*types.Transaction, error)) Option { func WithSignTxFunc(f func(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error)) Option {
return optionFunc(func(s *signerMock) { return optionFunc(func(s *signerMock) {
s.signTx = f s.signTx = f
}) })
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"errors" "errors"
"fmt" "fmt"
"math/big"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -23,7 +24,7 @@ type Signer interface { ...@@ -23,7 +24,7 @@ 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) Sign(data []byte) ([]byte, error)
// SignTx signs an ethereum transaction. // SignTx signs an ethereum transaction.
SignTx(transaction *types.Transaction) (*types.Transaction, error) SignTx(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error)
// SignTypedData signs data according to eip712. // SignTypedData signs data according to eip712.
SignTypedData(typedData *eip712.TypedData) ([]byte, error) SignTypedData(typedData *eip712.TypedData) ([]byte, error)
// PublicKey returns the public key this signer uses. // PublicKey returns the public key this signer uses.
...@@ -88,8 +89,9 @@ func (d *defaultSigner) Sign(data []byte) (signature []byte, err error) { ...@@ -88,8 +89,9 @@ func (d *defaultSigner) Sign(data []byte) (signature []byte, err error) {
} }
// SignTx signs an ethereum transaction. // SignTx signs an ethereum transaction.
func (d *defaultSigner) SignTx(transaction *types.Transaction) (*types.Transaction, error) { func (d *defaultSigner) SignTx(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
hash := (&types.HomesteadSigner{}).Hash(transaction).Bytes() txSigner := types.NewEIP155Signer(chainID)
hash := txSigner.Hash(transaction).Bytes()
// isCompressedKey is false here so we get the expected v value (27 or 28) // isCompressedKey is false here so we get the expected v value (27 or 28)
signature, err := d.sign(hash, false) signature, err := d.sign(hash, false)
if err != nil { if err != nil {
...@@ -98,7 +100,7 @@ func (d *defaultSigner) SignTx(transaction *types.Transaction) (*types.Transacti ...@@ -98,7 +100,7 @@ func (d *defaultSigner) SignTx(transaction *types.Transaction) (*types.Transacti
// v value needs to be adjusted by 27 as transaction.WithSignature expects it to be 0 or 1 // v value needs to be adjusted by 27 as transaction.WithSignature expects it to be 0 or 1
signature[64] -= 27 signature[64] -= 27
return transaction.WithSignature(&types.HomesteadSigner{}, signature) return transaction.WithSignature(txSigner, signature)
} }
// EthereumAddress returns the ethereum address this signer uses. // EthereumAddress returns the ethereum address this signer uses.
......
...@@ -101,14 +101,16 @@ func TestDefaultSignerSignTx(t *testing.T) { ...@@ -101,14 +101,16 @@ func TestDefaultSignerSignTx(t *testing.T) {
signer := crypto.NewDefaultSigner(privKey) signer := crypto.NewDefaultSigner(privKey)
beneficiary := common.HexToAddress("8d3766440f0d7b949a5e32995d09619a7f86e632") beneficiary := common.HexToAddress("8d3766440f0d7b949a5e32995d09619a7f86e632")
tx, err := signer.SignTx(types.NewTransaction(0, beneficiary, big.NewInt(0), 21000, big.NewInt(1), []byte{1})) chainID := big.NewInt(10)
tx, err := signer.SignTx(types.NewTransaction(0, beneficiary, big.NewInt(0), 21000, big.NewInt(1), []byte{1}), chainID)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
expectedR := math.MustParseBig256("0x28815033e9b5b7ec32e40e3c90b6cd499c12de8a7da261fdad8b800c845b88ef") expectedR := math.MustParseBig256("0x2937d18005a8236330b95c6b271ff46b06d5bf25355a06ff50939c9023245a99")
expectedS := math.MustParseBig256("0x71f1c08f754ee36e0c9743a2240d4b6640ea4d78c8dc2d83a599bdcf80ef9d5f") expectedS := math.MustParseBig256("0xcd7c13b2bb88a3d99004a80898fc05b50263f445f6c53ef7baf7ffca0e4a1bf")
expectedV := math.MustParseBig256("0x1c") expectedV := math.MustParseBig256("0x37")
v, r, s := tx.RawSignatureValues() v, r, s := tx.RawSignatureValues()
......
...@@ -153,19 +153,20 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -153,19 +153,20 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
if err != nil { if err != nil {
return nil, err return nil, err
} }
transactionService, err := transaction.NewService(logger, swapBackend, signer, stateStore)
chainID, err := swapBackend.ChainID(p2pCtx)
if err != nil { if err != nil {
return nil, err logger.Infof("could not connect to backend at %v. In a swap-enabled network a working blockchain node (for goerli network in production) is required. Check your node or specify another node using --swap-endpoint.", o.SwapEndpoint)
return nil, fmt.Errorf("could not get chain id from ethereum backend: %w", err)
} }
overlayEthAddress, err = signer.EthereumAddress()
transactionService, err := transaction.NewService(logger, swapBackend, signer, stateStore, chainID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
overlayEthAddress, err = signer.EthereumAddress()
chainID, err := swapBackend.ChainID(p2pCtx)
if err != nil { if err != nil {
logger.Infof("could not connect to backend at %v. In a swap-enabled network a working blockchain node (for goerli network in production) is required. Check your node or specify another node using --swap-endpoint.", o.SwapEndpoint) return nil, err
return nil, fmt.Errorf("could not get chain id from ethereum backend: %w", err)
} }
var factoryAddress common.Address var factoryAddress common.Address
......
...@@ -56,20 +56,23 @@ type transactionService struct { ...@@ -56,20 +56,23 @@ type transactionService struct {
signer crypto.Signer signer crypto.Signer
sender common.Address sender common.Address
store storage.StateStorer store storage.StateStorer
chainID *big.Int
} }
// NewService creates a new transaction service. // NewService creates a new transaction service.
func NewService(logger logging.Logger, backend Backend, signer crypto.Signer, store storage.StateStorer) (Service, error) { func NewService(logger logging.Logger, backend Backend, signer crypto.Signer, store storage.StateStorer, chainID *big.Int) (Service, error) {
senderAddress, err := signer.EthereumAddress() senderAddress, err := signer.EthereumAddress()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &transactionService{ return &transactionService{
logger: logger, logger: logger,
backend: backend, backend: backend,
signer: signer, signer: signer,
sender: senderAddress, sender: senderAddress,
store: store, store: store,
chainID: chainID,
}, nil }, nil
} }
...@@ -88,7 +91,7 @@ func (t *transactionService) Send(ctx context.Context, request *TxRequest) (txHa ...@@ -88,7 +91,7 @@ func (t *transactionService) Send(ctx context.Context, request *TxRequest) (txHa
return common.Hash{}, err return common.Hash{}, err
} }
signedTx, err := t.signer.SignTx(tx) signedTx, err := t.signer.SignTx(tx, t.chainID)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
......
...@@ -27,9 +27,9 @@ func nonceKey(sender common.Address) string { ...@@ -27,9 +27,9 @@ func nonceKey(sender common.Address) string {
return fmt.Sprintf("transaction_nonce_%x", sender) return fmt.Sprintf("transaction_nonce_%x", sender)
} }
func signerMockForTransaction(signedTx *types.Transaction, sender common.Address, t *testing.T) crypto.Signer { func signerMockForTransaction(signedTx *types.Transaction, sender common.Address, signerChainID *big.Int, t *testing.T) crypto.Signer {
return signermock.New( return signermock.New(
signermock.WithSignTxFunc(func(transaction *types.Transaction) (*types.Transaction, error) { signermock.WithSignTxFunc(func(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
if signedTx.To() == nil { if signedTx.To() == nil {
if transaction.To() != nil { if transaction.To() != nil {
t.Fatalf("signing transaction with recipient. wanted nil, got %x", transaction.To()) t.Fatalf("signing transaction with recipient. wanted nil, got %x", transaction.To())
...@@ -45,6 +45,9 @@ func signerMockForTransaction(signedTx *types.Transaction, sender common.Address ...@@ -45,6 +45,9 @@ func signerMockForTransaction(signedTx *types.Transaction, sender common.Address
if transaction.Value().Cmp(signedTx.Value()) != 0 { if transaction.Value().Cmp(signedTx.Value()) != 0 {
t.Fatalf("signing transaction with wrong value. wanted %d, got %d", signedTx.Value(), transaction.Value()) t.Fatalf("signing transaction with wrong value. wanted %d, got %d", signedTx.Value(), transaction.Value())
} }
if chainID.Cmp(signerChainID) != 0 {
t.Fatalf("signing transaction with wrong chainID. wanted %d, got %d", signerChainID, transaction.ChainId())
}
if transaction.Gas() != signedTx.Gas() { if transaction.Gas() != signedTx.Gas() {
t.Fatalf("signing transaction with wrong gas. wanted %d, got %d", signedTx.Gas(), transaction.Gas()) t.Fatalf("signing transaction with wrong gas. wanted %d, got %d", signedTx.Gas(), transaction.Gas())
} }
...@@ -73,6 +76,7 @@ func TestTransactionSend(t *testing.T) { ...@@ -73,6 +76,7 @@ func TestTransactionSend(t *testing.T) {
suggestedGasPrice := big.NewInt(2) suggestedGasPrice := big.NewInt(2)
estimatedGasLimit := uint64(3) estimatedGasLimit := uint64(3)
nonce := uint64(2) nonce := uint64(2)
chainID := big.NewInt(5)
t.Run("send", func(t *testing.T) { t.Run("send", func(t *testing.T) {
signedTx := types.NewTransaction(nonce, recipient, value, estimatedGasLimit, suggestedGasPrice, txData) signedTx := types.NewTransaction(nonce, recipient, value, estimatedGasLimit, suggestedGasPrice, txData)
...@@ -111,8 +115,9 @@ func TestTransactionSend(t *testing.T) { ...@@ -111,8 +115,9 @@ func TestTransactionSend(t *testing.T) {
return nonce - 1, nil return nonce - 1, nil
}), }),
), ),
signerMockForTransaction(signedTx, sender, t), signerMockForTransaction(signedTx, sender, chainID, t),
store, store,
chainID,
) )
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -170,8 +175,9 @@ func TestTransactionSend(t *testing.T) { ...@@ -170,8 +175,9 @@ func TestTransactionSend(t *testing.T) {
return nonce, nil return nonce, nil
}), }),
), ),
signerMockForTransaction(signedTx, sender, t), signerMockForTransaction(signedTx, sender, chainID, t),
store, store,
chainID,
) )
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -234,8 +240,9 @@ func TestTransactionSend(t *testing.T) { ...@@ -234,8 +240,9 @@ func TestTransactionSend(t *testing.T) {
return nextNonce, nil return nextNonce, nil
}), }),
), ),
signerMockForTransaction(signedTx, sender, t), signerMockForTransaction(signedTx, sender, chainID, t),
store, store,
chainID,
) )
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -292,8 +299,9 @@ func TestTransactionSend(t *testing.T) { ...@@ -292,8 +299,9 @@ func TestTransactionSend(t *testing.T) {
return nonce, nil return nonce, nil
}), }),
), ),
signerMockForTransaction(signedTx, sender, t), signerMockForTransaction(signedTx, sender, chainID, t),
storemock.NewStateStore(), storemock.NewStateStore(),
chainID,
) )
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -313,6 +321,7 @@ func TestTransactionSend(t *testing.T) { ...@@ -313,6 +321,7 @@ func TestTransactionSend(t *testing.T) {
func TestTransactionWaitForReceipt(t *testing.T) { func TestTransactionWaitForReceipt(t *testing.T) {
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
txHash := common.HexToHash("0xabcdee") txHash := common.HexToHash("0xabcdee")
chainID := big.NewInt(5)
transactionService, err := transaction.NewService(logger, transactionService, err := transaction.NewService(logger,
backendmock.New( backendmock.New(
...@@ -324,6 +333,7 @@ func TestTransactionWaitForReceipt(t *testing.T) { ...@@ -324,6 +333,7 @@ func TestTransactionWaitForReceipt(t *testing.T) {
), ),
signermock.New(), signermock.New(),
nil, nil,
chainID,
) )
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment