signer: add mutex around UI

This commit is contained in:
Martin Holst Swende 2017-11-27 13:22:47 +01:00
parent 37552ecc22
commit a601b38e40
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
2 changed files with 85 additions and 76 deletions

View file

@ -36,9 +36,6 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
//type Stringer interface {String()}
type SignerAPI struct { type SignerAPI struct {
chainID *big.Int chainID *big.Int
am *accounts.Manager am *accounts.Manager
@ -52,75 +49,67 @@ type Metadata struct {
scheme string scheme string
} }
type credPreference int // types for the requests/response types
type (
const ( // SignTxRequest contains info about a transaction to sign
forgetPw credPreference = iota SignTxRequest struct {
rememberPwNow transaction *types.Transaction
from accounts.Account
callinfo fmt.Stringer
}
// SignTxResponse result from SignTxRequest
SignTxResponse struct {
hash common.Hash
approved bool
pw string
}
// ExportRequest info about query to export accounts
ExportRequest struct {
account accounts.Account
file string
}
// ExportResponse response to export-request
ExportResponse struct {
approved bool
}
// ImportRequest info about request to import an account
ImportRequest struct {
account accounts.Account
}
ImportResponse struct {
approved bool
oldPassword string
newPassword string
}
SignDataRequest struct {
account accounts.Account
rawdata hexutil.Bytes
message string
hash hexutil.Bytes
}
SignDataResponse struct {
approved bool
pw string
}
NewAccountRequest struct{}
NewAccountResponse struct {
approved bool
pw string
}
ListRequest struct {
accounts []Account
}
ListResponse struct {
accounts []Account
}
) )
type Credentials struct { type errorWrapper struct {
password string
}
// SignTxRequest contains info about a transaction to sign
type SignTxRequest struct {
transaction *types.Transaction
from accounts.Account
callinfo fmt.Stringer
}
type SignTxResponse struct {
hash common.Hash
approved bool
pw string
}
type ExportRequest struct {
account accounts.Account
file string
}
type ExportResponse struct {
approved bool
}
type ImportRequest struct {
account accounts.Account
}
type ImportResponse struct {
approved bool
oldPassword string
newPassword string
}
type SignDataRequest struct {
account accounts.Account
rawdata hexutil.Bytes
message string
hash hexutil.Bytes
}
type SignDataResponse struct {
approved bool
pw string
}
type NewAccountRequest struct{}
type NewAccountResponse struct {
approved bool
pw string
}
type ListRequest struct {
accounts []Account
}
type ListResponse struct {
accounts []Account
}
type errorWrapper struct{
msg string msg string
err error err error
} }
func (ew errorWrapper) String() string{
func (ew errorWrapper) String() string {
return fmt.Sprintf("%s\n%s", ew.msg, ew.err) return fmt.Sprintf("%s\n%s", ew.msg, ew.err)
} }
@ -281,16 +270,16 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, from common.Address,
} }
req := SignTxRequest{transaction: tx, from: acc} req := SignTxRequest{transaction: tx, from: acc}
if len(tx.Data()) > 3{ if len(tx.Data()) > 3 {
var abidef string var abidef string
// Try to make sense of the data // Try to make sense of the data
abidef, err = lookupABI(tx.Data()[:4]) abidef, err = lookupABI(tx.Data()[:4])
if err != nil{ if err != nil {
req.callinfo = errorWrapper{"Warning! Could not locate ABI", err} req.callinfo = errorWrapper{"Warning! Could not locate ABI", err}
}else{ } else {
req.callinfo, err = parseCallData(tx.Data(),abidef) req.callinfo, err = parseCallData(tx.Data(), abidef)
if err != nil{ if err != nil {
req.callinfo = errorWrapper{"Warning! Could not validate ABI-data against calldata", err} req.callinfo = errorWrapper{"Warning! Could not validate ABI-data against calldata", err}
} }
} }

View file

@ -24,14 +24,16 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"sync"
) )
type CommandlineUI struct { type CommandlineUI struct {
in *bufio.Reader in *bufio.Reader
mu sync.Mutex
} }
func NewCommandlineUI() *CommandlineUI { func NewCommandlineUI() *CommandlineUI {
return &CommandlineUI{bufio.NewReader(os.Stdin)} return &CommandlineUI{in: bufio.NewReader(os.Stdin)}
} }
// readString reads a single line from stdin, trimming if from spaces, enforcing // readString reads a single line from stdin, trimming if from spaces, enforcing
@ -76,15 +78,18 @@ func showMetadata(metadata Metadata) {
// ApproveTx prompt the user for confirmation to request to sign transaction // ApproveTx prompt the user for confirmation to request to sign transaction
func (ui *CommandlineUI) ApproveTx(request *SignTxRequest, metadata Metadata, ch chan SignTxResponse) { func (ui *CommandlineUI) ApproveTx(request *SignTxRequest, metadata Metadata, ch chan SignTxResponse) {
ui.mu.Lock()
defer ui.mu.Unlock()
weival := request.transaction.Value() weival := request.transaction.Value()
fmt.Printf("--------- Transaction request-------------\n") fmt.Printf("--------- Transaction request-------------\n")
fmt.Printf("to: %v\n", request.transaction.To().Hex()) fmt.Printf("to: %v\n", request.transaction.To().Hex())
fmt.Printf("from: %v\n", request.from.Address.Hex()) fmt.Printf("from: %v\n", request.from.Address.Hex())
fmt.Printf("value: %v wei\n", weival) fmt.Printf("value: %v wei\n", weival)
fmt.Printf("data: %v\n", common.Bytes2Hex(request.transaction.Data())) if len(request.transaction.Data()) > 0{
if request.callinfo != nil{ fmt.Printf("data: %v\n", common.Bytes2Hex(request.transaction.Data()))
}
if request.callinfo != nil {
fmt.Printf("\nNote: This transaction contains data. Review abi-decoding info below:") fmt.Printf("\nNote: This transaction contains data. Review abi-decoding info below:")
fmt.Printf("\nCall info:\n\t%v\n", request.callinfo.String()) fmt.Printf("\nCall info:\n\t%v\n", request.callinfo.String())
@ -98,6 +103,8 @@ func (ui *CommandlineUI) ApproveTx(request *SignTxRequest, metadata Metadata, ch
// ApproveSignData prompt the user for confirmation to request to sign data // ApproveSignData prompt the user for confirmation to request to sign data
func (ui *CommandlineUI) ApproveSignData(request *SignDataRequest, metadata Metadata, ch chan SignDataResponse) { func (ui *CommandlineUI) ApproveSignData(request *SignDataRequest, metadata Metadata, ch chan SignDataResponse) {
ui.mu.Lock()
defer ui.mu.Unlock()
fmt.Printf("-------- Sign data request--------------\n") fmt.Printf("-------- Sign data request--------------\n")
fmt.Printf("account: %x\n", request.account.Address) fmt.Printf("account: %x\n", request.account.Address)
@ -111,6 +118,9 @@ func (ui *CommandlineUI) ApproveSignData(request *SignDataRequest, metadata Meta
// ApproveExport prompt the user for confirmation to export encrypted account json // ApproveExport prompt the user for confirmation to export encrypted account json
func (ui *CommandlineUI) ApproveExport(request *ExportRequest, metadata Metadata, ch chan ExportResponse) { func (ui *CommandlineUI) ApproveExport(request *ExportRequest, metadata Metadata, ch chan ExportResponse) {
ui.mu.Lock()
defer ui.mu.Unlock()
fmt.Printf("-------- Export account request--------------\n") fmt.Printf("-------- Export account request--------------\n")
fmt.Printf("A request has been made to export the (encrypted) keyfile\n") fmt.Printf("A request has been made to export the (encrypted) keyfile\n")
fmt.Printf("Approving this operation means that the caller obtains the (encrypted) contents\n") fmt.Printf("Approving this operation means that the caller obtains the (encrypted) contents\n")
@ -124,6 +134,9 @@ func (ui *CommandlineUI) ApproveExport(request *ExportRequest, metadata Metadata
// ApproveImport prompt the user for confirmation to import account json // ApproveImport prompt the user for confirmation to import account json
func (ui *CommandlineUI) ApproveImport(request *ImportRequest, metadata Metadata, ch chan ImportResponse) { func (ui *CommandlineUI) ApproveImport(request *ImportRequest, metadata Metadata, ch chan ImportResponse) {
ui.mu.Lock()
defer ui.mu.Unlock()
fmt.Printf("-------- Export account request--------------\n") fmt.Printf("-------- Export account request--------------\n")
fmt.Printf("A request has been made to import an encrypted keyfile\n") fmt.Printf("A request has been made to import an encrypted keyfile\n")
fmt.Printf("-------------------------------------------\n") fmt.Printf("-------------------------------------------\n")
@ -135,6 +148,9 @@ func (ui *CommandlineUI) ApproveImport(request *ImportRequest, metadata Metadata
// the list of accounts to list can be modified by the ui // the list of accounts to list can be modified by the ui
func (ui *CommandlineUI) ApproveListing(request *ListRequest, metadata Metadata, ch chan ListResponse) { func (ui *CommandlineUI) ApproveListing(request *ListRequest, metadata Metadata, ch chan ListResponse) {
ui.mu.Lock()
defer ui.mu.Unlock()
fmt.Printf("-------- List account request--------------\n") fmt.Printf("-------- List account request--------------\n")
fmt.Printf("A request has been made to list all accounts. \n") fmt.Printf("A request has been made to list all accounts. \n")
fmt.Printf("You can select which accounts the caller can see\n") fmt.Printf("You can select which accounts the caller can see\n")
@ -152,6 +168,10 @@ func (ui *CommandlineUI) ApproveListing(request *ListRequest, metadata Metadata,
// ApproveNewAccount prompt the user for confirmation to create new account, and reveal to caller // ApproveNewAccount prompt the user for confirmation to create new account, and reveal to caller
func (ui *CommandlineUI) ApproveNewAccount(requst *NewAccountRequest, metadata Metadata, ch chan NewAccountResponse) { func (ui *CommandlineUI) ApproveNewAccount(requst *NewAccountRequest, metadata Metadata, ch chan NewAccountResponse) {
ui.mu.Lock()
defer ui.mu.Unlock()
fmt.Printf("-------- New account request--------------\n") fmt.Printf("-------- New account request--------------\n")
fmt.Printf("A request has been made to create a new. \n") fmt.Printf("A request has been made to create a new. \n")
fmt.Printf("Approving this operation means that a new account is created,\n") fmt.Printf("Approving this operation means that a new account is created,\n")