Skip to content

Commit

Permalink
implement log replayer for files
Browse files Browse the repository at this point in the history
  • Loading branch information
solipsis committed Feb 15, 2019
1 parent a0186ac commit 2702280
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 67 deletions.
19 changes: 19 additions & 0 deletions cmd/replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"encoding/json"
"errors"
"io/ioutil"
"log"

"github.com/solipsis/go-keepkey/pkg/keepkey"
Expand Down Expand Up @@ -39,6 +40,24 @@ var replayCmd = &cobra.Command{

rec := keepkey.Record{Messages: []keepkey.LogMsg{lm}}
keepkey.Replay(kk, rec)
return
}

if logFile != "" {

buf, err := ioutil.ReadFile(logFile)
if err != nil {
log.Fatal(err)
}

r := keepkey.Record{}
json.Unmarshal(buf, &r)

if len(r.Messages) == 0 {
log.Fatal("Unable to parse messages, Validate that they are in valid JSON format")
}

keepkey.Replay(kk, r)
}

},
Expand Down
64 changes: 9 additions & 55 deletions pkg/keepkey/logreplay.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,19 @@ import (
"github.com/golang/protobuf/proto"
)

var test = `{"message_type":"EthereumSignTx","date":1550076468947,"message_enum":58,"message":{"addressNList":[2147483692,2147483708,2147483648,0,0],"nonce":"","gasPrice":"AVIabww=","gasLimit":"1PA=","to":"DYd19khDBnmnCemNKwy2JQ0oh+8=","value":"","dataInitialChunk":"qQWcuwAAAAAAAAAAAAAAAMU9lQ1zMBVO4yP8GfveHNZ5z763AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB29k+rNWL/AA=","dataLength":68,"toAddressNList":[],"addressType":3,"exchangeType":{"signedExchangeResponse":{"signature":"INyh1gt2zHXevVDuGDB8nYW2EH7mNDH7Ef0Qt1QD51ECXgkvyok+64dvHJSkVavoxwkjNH4neS+qfbbqKXTHuoQ=","responsev2":{"depositAddress":{"coinType":"bat","address":"0xc53d950d7330154ee323fc19fbde1cd679cfbeb7"},"depositAmount":"AdvZPqzVi/wA","expiration":1550077155180,"quotedRate":"BHUM45OVQAA=","withdrawalAddress":{"coinType":"ant","address":"0xbd5ffd40d55e9aee88a19f2340de40cadc60fc18"},"withdrawalAmount":"fuuj39He1AA=","returnAddress":{"coinType":"bat","address":"0xbd5ffd40d55e9aee88a19f2340de40cadc60fc18"},"apiKey":"atWDG3eEhLuEnaRRgKw1BHhI5crA+mZkVPT/eLjHOZ/qaozix+5ih7zXjbZhDKP1ONaz6QyoDI5jaLYCFEWVCw==","minerFee":"GelFjsQhwAA=","orderId":"Zw+8Oo1rRSykADwvwIrZAg=="}},"withdrawalCoinName":"ANT","withdrawalAddressNList":[2147483692,2147483708,2147483648,0,0],"returnAddressNList":[2147483692,2147483708,2147483648,0,0]},"chainId":1,"tokenValue":"","tokenTo":""},"from_device":false,"interface":"StandardWebUSB"}`

// Record blalahoeushtouthoesaut
type Record struct {
Messages []LogMsg `json:"messages"`
}

type LogMsg struct {
Type string `json:"message_type"`
Msg *json.RawMessage `json:"message"`
Type string `json:"message_type"`
FromDevice bool `json:"from_device"`
Msg *json.RawMessage `json:"message"`
}

//func Replay(kk *Keepkey, l []byte) {
//replay(
//}

// Replay plays a list of messages back to the device
//
func Replay(kk *Keepkey, r Record) {

for _, msg := range r.Messages {
Expand All @@ -37,46 +34,13 @@ func Replay(kk *Keepkey, r Record) {
continue
}

// Attempt to reflectively instantiate protobuf
proto, err := reflectJSON(msg.Type, []byte(*msg.Msg))
if err != nil {
log.Fatal(err)
}

err = kk.SendRaw(proto)
if err != nil {
log.Fatal(err)
}
fmt.Println("sent")

suc := new(kkProto.Success)
fmt.Println("Receiving")
err = kk.ReceiveRaw(suc)
if err != nil {
log.Fatal(err)
}

}

}

// Replay blah
// TODO: make bidirectional
/*
func Replay(kk *Keepkey, r io.Reader) {
fmt.Println("Replay")
sc := bufio.NewScanner(r)
for sc.Scan() {
lm := &logMsg{}
json.Unmarshal([]byte(sc.Text()), &lm)
if lm.Type == "" {
// TODO: implement validating received responses against what was previously received
if msg.FromDevice {
continue
}

// Attempt to reflectively instantiate protobuf
proto, err := reflectJSON(lm.Type, []byte(*lm.Msg))
proto, err := reflectJSON(msg.Type, []byte(*msg.Msg))
if err != nil {
log.Fatal(err)
}
Expand All @@ -85,23 +49,15 @@ func Replay(kk *Keepkey, r io.Reader) {
if err != nil {
log.Fatal(err)
}
fmt.Println("sent")

suc := new(kkProto.Success)
fmt.Println("Receiving")
err = kk.ReceiveRaw(suc)
_, err = kk.ReceiveRaw()
if err != nil {
log.Fatal(err)
}

}

// We got an error other than EOF
if sc.Err() != nil {
log.Fatal(sc.Err())
}
}
*/

// reflectJSON attempts to unmarshal a given json string into
// a reflected proto.Message using the typeName and typeRegistry
Expand All @@ -111,7 +67,6 @@ func reflectJSON(typeName string, body []byte) (proto.Message, error) {
return &kkProto.Ping{}, fmt.Errorf("No type with name %s found in TypeRegistry", typeName)
}

fmt.Println("Fetched Type: ", t)
p := reflect.New(t).Interface()

pr, ok := p.(proto.Message)
Expand All @@ -125,7 +80,6 @@ func reflectJSON(typeName string, body []byte) (proto.Message, error) {
if err != nil {
return &kkProto.Ping{}, fmt.Errorf("Unable to unmarshal parsed json:\n%s into type %s, With error: %s", body, typeName, err.Error())
}
fmt.Printf("PROTO: %T %+v\n", pr, pr)

return pr, nil
}
35 changes: 23 additions & 12 deletions pkg/keepkey/raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package keepkey
import (
"encoding/binary"
"fmt"
"reflect"
"strings"

"github.com/golang/protobuf/proto"
"github.com/solipsis/go-keepkey/pkg/kkProto"
Expand Down Expand Up @@ -47,10 +49,9 @@ func (kk *Keepkey) SendRaw(req proto.Message) error {
return nil
}

// ReceiveRaw receives a message from the device but does not take any additional actions based on the recieved message
// This is useful for recreating a previous exchange with the device
// TODO; make consistent with how debug/normal messages are handled in keepkeyExchange
func (kk *Keepkey) ReceiveRaw(result proto.Message) error {
// ReceiveRaw receives a message from the device but does not take any additional actions based on
// the recieved message. This is useful for recreating a previous exchange with the device
func (kk *Keepkey) ReceiveRaw() (proto.Message, error) {

response := <-kk.deviceQueue
kind := response.kind
Expand All @@ -62,19 +63,29 @@ func (kk *Keepkey) ReceiveRaw(result proto.Message) error {
// keepkey returned a failure, extract and return the message
failure := new(kkProto.Failure)
if err := proto.Unmarshal(reply, failure); err != nil {
return err
return &kkProto.Failure{}, err
}
return fmt.Errorf("keepkey: %s", failure.GetMessage())
return failure, fmt.Errorf("keepkey: %s", failure.GetMessage())
}

fmt.Println("kind", kind)
// reflectively instiate the appropriate type
typeName := strings.TrimPrefix(kkProto.Name(kind), "MessageType_")
t, ok := kkProto.TypeRegistry(typeName)
if !ok {
return &kkProto.Failure{}, fmt.Errorf("No type with name %s found in TypeRegistry", typeName)
}
p := reflect.New(t).Interface()
pr, ok := p.(proto.Message)
if !ok {
return &kkProto.Failure{}, fmt.Errorf("Reflected type does not implement proto.Message")
}

// If the reply we got can be marshaled into our expected result marshal it
if kkProto.Type(result) == kind {
err := proto.Unmarshal(reply, result)
kk.log("Recieved message from device:\n%s:\n%s", kkProto.Name(kkProto.Type(result)), pretty(result))
return err
if kkProto.Type(pr) == kind {
err := proto.Unmarshal(reply, pr)
kk.log("Recieved message from device:\n%s:\n%s", kkProto.Name(kkProto.Type(pr)), pretty(pr))
return &kkProto.Failure{}, err
}

return fmt.Errorf("keepkey: expected reply type %s, got %s", kkProto.Name(kkProto.Type(result)), kkProto.Name(kind))
return &kkProto.Failure{}, fmt.Errorf("keepkey: expected reply type %s, got %s", kkProto.Name(kkProto.Type(pr)), kkProto.Name(kind))
}

0 comments on commit 2702280

Please sign in to comment.