From ad67a69f99aba7ee39d379269b36c33bec6fb948 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Wed, 10 Mar 2021 14:33:15 -0500 Subject: [PATCH] Adjust Ethereum contracts to use EIP155 signer go-ethereum 1.10.0 has switched to denying non-EIP155 signatures by default. Although our code uses go-ethereum's own ABI binding generation, the version currently in our dependencies never added support for EIP155 signers, and instead always uses Homestead signers for the transactors it provides helpers for. In the short term, this commit manually creates the transactor options for the account key, forcing an EIP155 signer when doing signing. When the go-ethereum dependency gets bumped past 1.9.25, we will be able to move back to `NewKeyedTransactorWithChainID`, which uses an EIP155 signer under the hood. --- tools/generators/ethereum/command.go.tmpl | 9 +++++++ .../ethereum/command_template_content.go | 9 +++++++ tools/generators/ethereum/contract.go.tmpl | 24 ++++++++++++++++--- .../ethereum/contract_template_content.go | 24 ++++++++++++++++--- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/tools/generators/ethereum/command.go.tmpl b/tools/generators/ethereum/command.go.tmpl index beab0e1a..1f2e0f2d 100644 --- a/tools/generators/ethereum/command.go.tmpl +++ b/tools/generators/ethereum/command.go.tmpl @@ -204,6 +204,14 @@ func initialize{{.Class}}(c *cli.Context) (*contract.{{.Class}}, error) { return nil, fmt.Errorf("error connecting to Ethereum node: [%v]", err) } + chainID, err := client.ChainID(context.Background()) + if err != nil { + return nil, fmt.Errorf( + "failed to resolve Ethereum chain id: [%v]", + err, + ) + } + key, err := ethutil.DecryptKeyFile( config.Account.KeyFile, config.Account.KeyFilePassword, @@ -239,6 +247,7 @@ func initialize{{.Class}}(c *cli.Context) (*contract.{{.Class}}, error) { return contract.New{{.Class}}( address, + chainID, key, client, ethutil.NewNonceManager(key.Address, client), diff --git a/tools/generators/ethereum/command_template_content.go b/tools/generators/ethereum/command_template_content.go index f5e09ea1..2c7c3808 100644 --- a/tools/generators/ethereum/command_template_content.go +++ b/tools/generators/ethereum/command_template_content.go @@ -207,6 +207,14 @@ func initialize{{.Class}}(c *cli.Context) (*contract.{{.Class}}, error) { return nil, fmt.Errorf("error connecting to Ethereum node: [%v]", err) } + chainID, err := client.ChainID(context.Background()) + if err != nil { + return nil, fmt.Errorf( + "failed to resolve Ethereum chain id: [%v]", + err, + ) + } + key, err := ethutil.DecryptKeyFile( config.Account.KeyFile, config.Account.KeyFilePassword, @@ -242,6 +250,7 @@ func initialize{{.Class}}(c *cli.Context) (*contract.{{.Class}}, error) { return contract.New{{.Class}}( address, + chainID, key, client, ethutil.NewNonceManager(key.Address, client), diff --git a/tools/generators/ethereum/contract.go.tmpl b/tools/generators/ethereum/contract.go.tmpl index 549db2d4..5bd60425 100644 --- a/tools/generators/ethereum/contract.go.tmpl +++ b/tools/generators/ethereum/contract.go.tmpl @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ipfs/go-log" @@ -44,6 +45,7 @@ type {{.Class}} struct { func New{{.Class}}( contractAddress common.Address, + chainId *big.Int, accountKey *keystore.Key, backend bind.ContractBackend, nonceManager *ethutil.NonceManager, @@ -55,9 +57,25 @@ func New{{.Class}}( From: accountKey.Address, } - transactorOptions := bind.NewKeyedTransactor( - accountKey.PrivateKey, - ) + // FIXME Switch to bind.NewKeyedTransactorWithChainID when go-ethereum dep + // FIXME bumps beyond 1.9.25. + key := accountKey.PrivateKey + keyAddress := crypto.PubkeyToAddress(key.PublicKey) + transactorOptions := &bind.TransactOpts{ + From: keyAddress, + Signer: func(_ types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) { + signer := types.NewEIP155Signer(chainId) + + if address != keyAddress { + return nil, fmt.Errorf("not authorized to sign this account") + } + signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key) + if err != nil { + return nil, err + } + return tx.WithSignature(signer, signature) + }, + } randomBeaconContract, err := abi.New{{.AbiClass}}( contractAddress, diff --git a/tools/generators/ethereum/contract_template_content.go b/tools/generators/ethereum/contract_template_content.go index 34f016de..1bc72e17 100644 --- a/tools/generators/ethereum/contract_template_content.go +++ b/tools/generators/ethereum/contract_template_content.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ipfs/go-log" @@ -47,6 +48,7 @@ type {{.Class}} struct { func New{{.Class}}( contractAddress common.Address, + chainId *big.Int, accountKey *keystore.Key, backend bind.ContractBackend, nonceManager *ethutil.NonceManager, @@ -58,9 +60,25 @@ func New{{.Class}}( From: accountKey.Address, } - transactorOptions := bind.NewKeyedTransactor( - accountKey.PrivateKey, - ) + // FIXME Switch to bind.NewKeyedTransactorWithChainID when go-ethereum dep + // FIXME bumps beyond 1.9.25. + key := accountKey.PrivateKey + keyAddress := crypto.PubkeyToAddress(key.PublicKey) + transactorOptions := &bind.TransactOpts{ + From: keyAddress, + Signer: func(_ types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) { + signer := types.NewEIP155Signer(chainId) + + if address != keyAddress { + return nil, fmt.Errorf("not authorized to sign this account") + } + signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key) + if err != nil { + return nil, err + } + return tx.WithSignature(signer, signature) + }, + } randomBeaconContract, err := abi.New{{.AbiClass}}( contractAddress,