From 84cb4c7130dde83eb05eea93be9c9f61ea71fd65 Mon Sep 17 00:00:00 2001
From: Dave Collins <davec@conformal.com>
Date: Fri, 3 Jan 2014 10:22:37 -0600
Subject: [PATCH] Export new function ConvertCreateRawTxParams.

The inputs to the createrawtransaction command are JSON strings, however
the NewCreateRawTransactionCmd function takes concrete types.  Thus,
callers which deal with the raw JSON need a method to perform the
validation and conversion.  This logic is the same as what needs to happen
when unmashalling a full JSON-RPC command, so this commit factors that
logic out into a separate function and exports it.
---
 jsoncmd.go | 112 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 63 insertions(+), 49 deletions(-)

diff --git a/jsoncmd.go b/jsoncmd.go
index af55cc93..44406612 100644
--- a/jsoncmd.go
+++ b/jsoncmd.go
@@ -709,6 +709,65 @@ type TransactionInput struct {
 	Vout int    `json:"vout"`
 }
 
+// ConvertCreateRawTxParams validates and converts the passed parameters from
+// raw interfaces into concrete structs.  This is a separate function since
+// the createrawtransaction command parameters are caller-crafted JSON as
+// opposed to machine generated JSON as is the case for most commands.
+func ConvertCreateRawTxParams(inputs, amounts interface{}) ([]TransactionInput, map[string]int64, error) {
+	iinputs, ok := inputs.([]interface{})
+	if !ok {
+		return nil, nil, errors.New("first parameter inputs must be an array")
+	}
+	rinputs := make([]TransactionInput, len(iinputs))
+	for i, iv := range iinputs {
+		v, ok := iv.(map[string]interface{})
+		if !ok {
+			return nil, nil, errors.New("first parameter inputs must be an array of objects")
+		}
+
+		if len(v) != 2 {
+			return nil, nil, errors.New("input with wrong number of members")
+		}
+		txid, ok := v["txid"]
+		if !ok {
+			return nil, nil, errors.New("input without txid")
+		}
+		rinputs[i].Txid, ok = txid.(string)
+		if !ok {
+			return nil, nil, errors.New("input txid isn't a string")
+		}
+
+		vout, ok := v["vout"]
+		if !ok {
+			return nil, nil, errors.New("input without vout")
+		}
+		fvout, ok := vout.(float64)
+		if !ok {
+			return nil, nil, errors.New("input vout not a number")
+		}
+		rinputs[i].Vout = int(fvout)
+	}
+	famounts, ok := amounts.(map[string]interface{})
+	if !ok {
+		return nil, nil, errors.New("second parameter keys must be a map")
+	}
+
+	ramounts := make(map[string]int64)
+	for k, v := range famounts {
+		fv, ok := v.(float64)
+		if !ok {
+			return nil, nil, errors.New("second parameter keys must be a number map")
+		}
+		var err error
+		ramounts[k], err = JSONToAmount(fv)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+
+	return rinputs, ramounts, nil
+}
+
 // CreateRawTransactionCmd is a type handling custom marshaling and
 // unmarshaling of createrawtransaction JSON RPC commands.
 type CreateRawTransactionCmd struct {
@@ -770,56 +829,11 @@ func (cmd *CreateRawTransactionCmd) UnmarshalJSON(b []byte) error {
 	if len(r.Params) != 2 {
 		return ErrWrongNumberOfParams
 	}
-	iinputs, ok := r.Params[0].([]interface{})
-	if !ok {
-		return errors.New("first parameter inputs must be an array")
-	}
-	inputs := make([]TransactionInput, len(iinputs))
-	for i, iv := range iinputs {
-		v, ok := iv.(map[string]interface{})
-		if !ok {
-			return errors.New("first parameter inputs must be an array of objects")
-		}
 
-		if len(v) != 2 {
-			return errors.New("input with wrong number of members")
-		}
-		txid, ok := v["txid"]
-		if !ok {
-			return errors.New("input without txid")
-		}
-		inputs[i].Txid, ok = txid.(string)
-		if !ok {
-			return errors.New("input txid isn't a string")
-		}
-
-		vout, ok := v["vout"]
-		if !ok {
-			return errors.New("input without vout")
-		}
-		fvout, ok := vout.(float64)
-		if !ok {
-			return errors.New("input vout not a number")
-		}
-		inputs[i].Vout = int(fvout)
-	}
-	cmd.Inputs = inputs
-	famounts, ok := r.Params[1].(map[string]interface{})
-	if !ok {
-		return errors.New("second parameter keys must be a map")
-	}
-
-	amounts := make(map[string]int64)
-	for k, v := range famounts {
-		fv, ok := v.(float64)
-		if !ok {
-			return errors.New("second parameter keys must  be a number map")
-		}
-		var err error
-		amounts[k], err = JSONToAmount(fv)
-		if err != nil {
-			return err
-		}
+	inputs, amounts, err := ConvertCreateRawTxParams(r.Params[0],
+		r.Params[1])
+	if err != nil {
+		return err
 	}
 
 	newCmd, err := NewCreateRawTransactionCmd(r.Id, inputs, amounts)