diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f90dc8e --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module github.com/immutability-io/go-ethereum-hdwallet + +go 1.12 + +require ( + github.com/aristanetworks/goarista v0.0.0-20180627184309-2c5933638c5e + github.com/btcsuite/btcd v0.0.0-20180531025944-86fed781132a + github.com/btcsuite/btcutil v0.0.0-20180524032703-d4cc87b86016 + github.com/davecgh/go-spew v1.1.0 + github.com/ethereum/go-ethereum v1.8.11 + github.com/go-stack/stack v1.7.0 + github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db + github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0 + github.com/syndtr/goleveldb v0.0.0-20180621010148-0d5a0ceb10cf + github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8 + golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 + gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..64379dc --- /dev/null +++ b/go.sum @@ -0,0 +1,24 @@ +github.com/aristanetworks/goarista v0.0.0-20180627184309-2c5933638c5e h1:GfUJvUv57+W9J0lpQB5/hsdv43F46ffAJewlooRGXXo= +github.com/aristanetworks/goarista v0.0.0-20180627184309-2c5933638c5e/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/btcsuite/btcd v0.0.0-20180531025944-86fed781132a h1:fuEu3WaOzatbWFGlCa2e/TL/GR397Da8QSKNKrDRa3s= +github.com/btcsuite/btcd v0.0.0-20180531025944-86fed781132a/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/btcsuite/btcutil v0.0.0-20180524032703-d4cc87b86016 h1:BsZAJgCuMsoFZMZNyj7Lyt6sS8anDhedVrAMCOyPMIo= +github.com/btcsuite/btcutil v0.0.0-20180524032703-d4cc87b86016/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/ethereum/go-ethereum v1.8.11 h1:BQW9TK1H8xRYQ23M1SRzc/C4dePhYYAH31krY0xs1vU= +github.com/ethereum/go-ethereum v1.8.11/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= +github.com/go-stack/stack v1.7.0 h1:S04+lLfST9FvL8dl4R31wVUC/paZp/WQZbLmUgWboGw= +github.com/go-stack/stack v1.7.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0 h1:DmK33IJe81zJOzLmzzBHWf2/fGB0tnvqLnvGu8S5wYY= +github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0/go.mod h1:VVt+rn/itmf+9eZq9CAabVlsfsHveUNUQ0bRv3ChqxY= +github.com/syndtr/goleveldb v0.0.0-20180621010148-0d5a0ceb10cf h1:QDa82vuIQYktiygoQ49yLjSwCsHFxcDWsWsENaIm33I= +github.com/syndtr/goleveldb v0.0.0-20180621010148-0d5a0ceb10cf/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8 h1:g3yQGZK+G6dfF/mw/SOwsTMzUVkpT4hB8pHxpbTXkKw= +github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8 h1:h7zdf0RiEvWbYBKIx4b+q41xoUVnMmvsGZnIVE5syG8= +golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951 h1:DMTcQRFbEH62YPRWwOI647s2e5mHda3oBPMHfrLs2bw= +gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951/go.mod h1:owOxCRGGeAx1uugABik6K9oeNu1cgxP/R9ItzLDxNWA= diff --git a/hdwallet.go b/hdwallet.go index d4ed97e..80dc3fa 100644 --- a/hdwallet.go +++ b/hdwallet.go @@ -216,6 +216,41 @@ func (w *Wallet) SignHash(account accounts.Account, hash []byte) ([]byte, error) return crypto.Sign(hash, privateKey) } +// SignTxEIP155 implements accounts.Wallet, which allows the account to sign an ERC-20 transaction. +func (w *Wallet) SignTxEIP155(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + w.stateLock.RLock() // Comms have own mutex, this is for the state fields + defer w.stateLock.RUnlock() + + // Make sure the requested account is contained within + path, ok := w.paths[account.Address] + if !ok { + return nil, accounts.ErrUnknownAccount + } + + privateKey, err := w.derivePrivateKey(path) + if err != nil { + return nil, err + } + + // Sign the transaction and verify the sender to avoid hardware fault surprises + signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey) + if err != nil { + return nil, err + } + + msg, err := signedTx.AsMessage(types.NewEIP155Signer(chainID)) + if err != nil { + return nil, err + } + + sender := msg.From() + if sender != account.Address { + return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex()) + } + + return signedTx, nil +} + // SignTx implements accounts.Wallet, which allows the account to sign an Ethereum transaction. func (w *Wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { w.stateLock.RLock() // Comms have own mutex, this is for the state fields