Skip to content

Commit

Permalink
[cli] refs fibercrypto#146 Modifying transactionSign command
Browse files Browse the repository at this point in the history
  • Loading branch information
adriantpaez committed Jul 27, 2019
1 parent d982bdd commit 84e3605
Showing 1 changed file with 113 additions and 65 deletions.
178 changes: 113 additions & 65 deletions src/cli/transaction_sign.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package cli

import (
"errors"
"fmt"
"github.com/skycoin/hardware-wallet-go/src/skywallet/wire"
"os"
"runtime"

Expand Down Expand Up @@ -88,89 +90,89 @@ func transactionSignCmd() gcli.Command {
}

if len(inputs) > 7 || len(outputs) > 7 {
println("Start big transaction protocol.")
state := 0
index := 0

// Building an send first SignTx message
msg, err := device.SignTx(len(outputs), len(inputs), coinName, version, lockTime, txHash)
if err != nil {
log.Error(err)
return
}
if msg.Kind != uint16(messages.MessageType_MessageType_TxRequest) {
log.Error("Unexpected response message type from hardware wallet.")
return
}
txRequest := &messages.TxRequest{}
err = proto.Unmarshal(msg.Data, txRequest)
if err != nil {
log.Error(err)
return
}
if *txRequest.RequestType != messages.TxRequest_TXINPUT {
log.Error("Unexpected reuqest type")
return
}

var txInputs []*messages.TxAck_TransactionType_TxInputType
var txOutputs []*messages.TxAck_TransactionType_TxOutputType

// Sending Inputs
for i, input := range inputs {
if len(txInputs) == 7 {
msg, err := device.TxAck(txInputs, []*messages.TxAck_TransactionType_TxOutputType{}, version, lockTime)
if err != nil {
log.Error(err)
return
}
if msg.Kind != uint16(messages.MessageType_MessageType_TxRequest) {
log.Error("Unexpected response message type from hardware wallet.")
return
}
txInputs = []*messages.TxAck_TransactionType_TxInputType{}
}
var txInput messages.TxAck_TransactionType_TxInputType
txInput.AddressN = []uint32{*proto.Uint32(uint32(inputIndex[i]))}
txInput.HashIn = proto.String(input)
txInputs = append(txInputs, &txInput)
}
if len(txInputs) != 0 {
_, err := device.TxAck(txInputs, txOutputs, version, lockTime)
for {
if err != nil {
log.Error(err)
return
}
txInputs = []*messages.TxAck_TransactionType_TxInputType{}
}

// Sending Outputs
for i, output := range outputs {
if len(txOutputs) == 7 {
msg, err := device.TxAck(txInputs, txOutputs, version, lockTime)
switch msg.Kind {
case uint16(messages.MessageType_MessageType_TxRequest):
txRequest := &messages.TxRequest{}
err = proto.Unmarshal(msg.Data, txRequest)
if err != nil {
log.Error(err)
return
}
if msg.Kind != uint16(messages.MessageType_MessageType_TxRequest) {
log.Error("Unexpected response message type from hardware wallet.")
switch *txRequest.RequestType {
case messages.TxRequest_TXINPUT:
if state == 0 {
// Sending Inputs
msg, err = sendInputs(device,&inputs,&inputIndex,version,lockTime,&index,&state)
} else if state == 2 {
// Printing Signatures
txRequest := &messages.TxRequest{}
err = proto.Unmarshal(msg.Data, txRequest)
if err != nil {
log.Error(err)
return
}
for _, sign := range txRequest.SignResult {
println(*sign.Signature)
}
// Sending Inputs for signatures
msg, err = sendInputs(device,&inputs,&inputIndex,version,lockTime,&index,&state)
} else {
log.Error("Protocol error: unexpected TxRequest type")
return
}
case messages.TxRequest_TXOUTPUT:
if state == 1 {
// Sending Outputs
msg, err = sendOutputs(device,&outputs,&addressIndex,&coins,&hours,version,lockTime,&index,&state)
} else {
log.Error("Protocol error: unexpected TxRequest type")
return
}
case messages.TxRequest_TXFINISHED:
if state == 3 {
txRequest := &messages.TxRequest{}
err = proto.Unmarshal(msg.Data, txRequest)
if err != nil {
log.Error(err)
return
}
for _, sign := range txRequest.SignResult {
println(*sign.Signature)
}
return
} else {
log.Error("protocol error: unexpected TXFINISHED message")
return
}
}
case uint16(messages.MessageType_MessageType_Failure):
failMsg, err := skyWallet.DecodeFailMsg(msg)
if err != nil {
log.Error(err)
return
}
txOutputs = []*messages.TxAck_TransactionType_TxOutputType{}
}
var txOutput messages.TxAck_TransactionType_TxOutputType
txOutput.Address = proto.String(output)
if i < len(addressIndex) {
txOutput.AddressN = []uint32{uint32(addressIndex[i])}
}
txOutput.Coins = proto.Uint64(uint64(coins[i]))
txOutput.Hours = proto.Uint64(uint64(hours[i]))
txOutputs = append(txOutputs, &txOutput)
}
if len(txOutputs) != 0 {
_, err := device.TxAck(txInputs, txOutputs, version, lockTime)
if err != nil {
log.Error(err)
fmt.Printf("Failed with message: %s\n", failMsg)
return
case uint16(messages.MessageType_MessageType_ButtonRequest):
msg, err = device.ButtonAck()
default:
log.Error("Unexpected response message type from hardware wallet.")
return
}
txOutputs = []*messages.TxAck_TransactionType_TxOutputType{}
}
} else {
var transactionInputs []*messages.SkycoinTransactionInput
Expand Down Expand Up @@ -253,3 +255,49 @@ func transactionSignCmd() gcli.Command {
},
}
}

func sendInputs(device *skyWallet.Device, inputs *[]string, inputIndex *[]int, version int, lockTime int,index *int,state *int)(wire.Message, error){
var txInputs []*messages.TxAck_TransactionType_TxInputType
startIndex := *index
for i, input := range (*inputs)[*index:] {
if len(txInputs) == 7 {
return device.TxAck(txInputs, []*messages.TxAck_TransactionType_TxOutputType{}, version, lockTime)
}
var txInput messages.TxAck_TransactionType_TxInputType
txInput.AddressN = []uint32{*proto.Uint32(uint32((*inputIndex)[startIndex+i]))}
txInput.HashIn = proto.String(input)
txInputs = append(txInputs, &txInput)
*index++
}
if len(txInputs) != 0 {
*index = 0
*state++
return device.TxAck(txInputs, nil, version, lockTime)
}
return wire.Message{}, errors.New("empty inputs")
}

func sendOutputs(device *skyWallet.Device, outputs *[]string, addressIndex *[]int, coins *[]int64, hours *[]int64, version int, lockTime int, index *int, state *int)(wire.Message, error){
var txOutputs []*messages.TxAck_TransactionType_TxOutputType
startIndex := *index
for i, output := range (*outputs)[*index:] {
if len(txOutputs) == 7 {
return device.TxAck(nil, txOutputs, version, lockTime)
}
var txOutput messages.TxAck_TransactionType_TxOutputType
txOutput.Address = proto.String(output)
if i < len(*addressIndex) {
txOutput.AddressN = []uint32{uint32((*addressIndex)[startIndex+i])}
}
txOutput.Coins = proto.Uint64(uint64((*coins)[startIndex+i]))
txOutput.Hours = proto.Uint64(uint64((*hours)[startIndex+i]))
txOutputs = append(txOutputs, &txOutput)
*index++
}
if len(txOutputs) != 0 {
*index = 0
*state++
return device.TxAck(nil, txOutputs, version, lockTime)
}
return wire.Message{}, errors.New("empty outputs")
}

0 comments on commit 84e3605

Please sign in to comment.