Skip to content

Commit

Permalink
fix ethereum signing. Ethereum signing tests, better flags and defaul…
Browse files Browse the repository at this point in the history
…ts for etherum signing, re-enable debug pressing
  • Loading branch information
solipsis committed Mar 15, 2018
1 parent 97f0e7f commit a4917c8
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 17 deletions.
46 changes: 31 additions & 15 deletions cmd/signEthTx.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import (
)

func init() {
signEthTxCmd.Flags().StringVarP(&nonce, "nonce", "", "", "Nonce value for transaction")
signEthTxCmd.Flags().StringVarP(&nonce, "nonce", "n", "", "Nonce value for transaction")
signEthTxCmd.Flags().StringVarP(&recipient, "to", "t", "", "Address to send to")
signEthTxCmd.Flags().StringVarP(&amount, "amount", "a", "", "Amount of eth in wei")
signEthTxCmd.Flags().StringVarP(&gasLimit, "gasLimit", "l", "100000", "Gas limit in wei")
signEthTxCmd.Flags().StringVarP(&gasPrice, "gasPrice", "p", "", "Gas price in wei")
signEthTxCmd.Flags().StringVarP(&nodePath, "nodePath", "", "44'/60'/0'/0/0", "BIP44 node path")
rootCmd.AddCommand(signEthTxCmd)
}

Expand All @@ -33,29 +34,44 @@ var signEthTxCmd = &cobra.Command{
Long: "Signs an ethereum transaction",
Run: func(cmd *cobra.Command, args []string) {

//TODO; cleanup this interaction
// amount, gasLimit, gasPrice
var amt, gl, gp *big.Int = new(big.Int), new(big.Int), new(big.Int)
path, err := keepkey.ParsePath(nodePath)
if err != nil {
fmt.Println("Invalid node path:", err)
os.Exit(1)
}

amt, success := new(big.Int).SetString(amount, 10)
if !success {
fmt.Println("Unable to parse amount")
os.Exit(1)
}

limit, success := new(big.Int).SetString(gasLimit, 10)
if !success {
fmt.Println("Unable to parse gas limit")
os.Exit(1)
}

price, success := new(big.Int).SetString(gasPrice, 10)
if !success {
fmt.Println("Unable to parse price")
os.Exit(1)
}

n, err := strconv.ParseUint(nonce, 10, 64)
if err != nil {
fmt.Println(err)
fmt.Println("Unable to parse nonce:", err)
os.Exit(1)
}
// parse amount gaslimit gasprice
amt, oka := amt.SetString(amount, 10)
gl, okgl := gl.SetString(gasLimit, 10)
gp, okgp := gl.SetString(gasPrice, 10)

// fail if any values could not be parsed
if !(oka && okgl && okgp) {
fmt.Println("Unable to parse values")
// TODO: adjust data param when the keepkey reenables arbitrary data fields
tx := keepkey.NewTransaction(n, recipient, amt, limit, price, []byte{})
tx, err = kk.EthereumSignTx(path, tx)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

tx := keepkey.NewTransaction(n, recipient, amt, gl, gp, []byte{})
kk.EthereumSignTx([]uint32{0}, tx)

raw, err := tx.ToRawTransaction()
if err != nil {
fmt.Println(err)
Expand Down
86 changes: 86 additions & 0 deletions pkg/keepkey/ethereum_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package keepkey

import (
"encoding/hex"
"math/big"
"strings"
"testing"
)

func TestSignEthTx(t *testing.T) {

kk.WipeDevice()
words := "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong"
if err := kk.LoadDevice(strings.Split(words, " "), "", "", false, true); err != nil {
t.Error("Unable to load device from seed words", err)
}

var nonce uint64 = 20
recipient := "0x6b67c94fc31510707f9c0f1281aad5ec9a2eeff0"
amount := big.NewInt(1337)
gasLimit := big.NewInt(80000)
gasPrice := big.NewInt(22000000000)
data := []byte{}
tx := NewTransaction(nonce, recipient, amount, gasLimit, gasPrice, data)

tx, err := kk.EthereumSignTx(ethPath, tx)
if err != nil {
t.Errorf("Unable to sign tx: %s", err)
}

expectedSigV := "1b"
expectedSigR := "98f67b760034d1b9237c3fc2212886dffb6bf04ea66e7a6d775ccabd1dcca2d6"
expectedSigS := "3e3fd19e263a0bc1d05345f915a359d04ccd13296f80a0249a9d81697832533e"

v := hex.EncodeToString([]byte{byte(tx.V)})
r := hex.EncodeToString(tx.R)
s := hex.EncodeToString(tx.S)

if v != expectedSigV || r != expectedSigR || s != expectedSigS {
t.Errorf("Incorrect Signature values, expected V: %s R: %s S: %s, got V: %s, R: %s, S:%s",
expectedSigV, expectedSigR, expectedSigS, v, r, s)
}
}

func TestToRawTransaction(t *testing.T) {

var nonce uint64 = 20
recipient := "0x6b67c94fc31510707f9c0f1281aad5ec9a2eeff0"
amount := big.NewInt(1337)
gasLimit := big.NewInt(80000)
gasPrice := big.NewInt(22000000000)
data := []byte{}
tx := NewTransaction(nonce, recipient, amount, gasLimit, gasPrice, data)

tx, err := kk.EthereumSignTx(ethPath, tx)
if err != nil {
t.Errorf("Unable to sign tx: %s", err)
}

raw, err := tx.ToRawTransaction()
if err != nil {
t.Error("Unable to convert to raw tx:", err)
}

expected := "0xf8671485051f4d5c0083013880946b67c94fc31510707f9c0f1281aad5ec9a2eeff0820539801ba098f67b760034d1b9237c3fc2212886dffb6bf04ea66e7a6d775ccabd1dcca2d6a03e3fd19e263a0bc1d05345f915a359d04ccd13296f80a0249a9d81697832533e"

if raw != expected {
t.Errorf("Incorrect raw tx, expected: %s, got: %s", expected, raw)
}
}

func TestNewTransaction(t *testing.T) {

var nonce uint64 = 20
recipient := "0x6b67c94fc31510707f9c0f1281aad5ec9a2eeff0"
amount := big.NewInt(1337)
gasLimit := big.NewInt(80000)
gasPrice := big.NewInt(21000000000)
data := []byte{}
tx := NewTransaction(nonce, recipient, amount, gasLimit, gasPrice, data)

if tx.Nonce != nonce || tx.Recipient != recipient || tx.Amount.String() != "1337" ||
tx.GasLimit.String() != "80000" || tx.GasPrice.String() != "21000000000" || len(data) > 0 {
t.Errorf("Incorrect transaction created: %v", tx)
}
}
1 change: 1 addition & 0 deletions pkg/keepkey/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ func (kk *Keepkey) EthereumSignTx(derivationPath []uint32, tx *EthereumTx) (*Eth
}

resp, err := kk.ethereumSignTx(est)

if err != nil {
return tx, errors.New("Unable to sign transaction:" + err.Error())
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/keepkey/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ func (kk *Keepkey) keepkeyExchange(req proto.Message, results ...proto.Message)
if kind == uint16(kkProto.MessageType_MessageType_ButtonRequest) {
promptButton()
if kk.debug != nil {
//t := true
t := true
fmt.Println("sending debug press")
//kk.keepkeyExchange(&kkProto.DebugLinkDecision{YesNo: &t}, &kkProto.Success{})
kk.keepkeyExchange(&kkProto.DebugLinkDecision{YesNo: &t}, &kkProto.Success{})
}
return kk.keepkeyExchange(&kkProto.ButtonAck{}, results...)
}
Expand Down

0 comments on commit a4917c8

Please sign in to comment.