Small changes to createVinList/createVoutList

Added error checking for script disassembley

Changed vout to handle errors in processing the way bitcoind does: the
type displayed is "nonstandard" when the calculated type is nonstandard
or nulltype and also when there is an error getting the address.

Still doesn't properly support multisig addresses, but now it should
return "nonstandard" since since address lookup fails for those cases.
This commit is contained in:
Francis Lam 2013-12-30 20:06:13 -05:00
parent eb624acfd4
commit 28d08f8b16

View file

@ -35,7 +35,6 @@ import (
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -700,7 +699,7 @@ func handleDebugLevel(s *rpcServer, cmd btcjson.Cmd,
// createVinList returns a slice of JSON objects for the inputs of the passed // createVinList returns a slice of JSON objects for the inputs of the passed
// transaction. // transaction.
func createVinList(mtx *btcwire.MsgTx) []btcjson.Vin { func createVinList(mtx *btcwire.MsgTx) ([]btcjson.Vin, *btcjson.Error) {
tx := btcutil.NewTx(mtx) tx := btcutil.NewTx(mtx)
vinList := make([]btcjson.Vin, len(mtx.TxIn)) vinList := make([]btcjson.Vin, len(mtx.TxIn))
for i, v := range mtx.TxIn { for i, v := range mtx.TxIn {
@ -710,7 +709,13 @@ func createVinList(mtx *btcwire.MsgTx) []btcjson.Vin {
vinList[i].Txid = v.PreviousOutpoint.Hash.String() vinList[i].Txid = v.PreviousOutpoint.Hash.String()
vinList[i].Vout = int(v.PreviousOutpoint.Index) vinList[i].Vout = int(v.PreviousOutpoint.Index)
disbuf, _ := btcscript.DisasmString(v.SignatureScript) disbuf, err := btcscript.DisasmString(v.SignatureScript)
if err != nil {
return nil, &btcjson.Error{
Code: btcjson.ErrInternal.Code,
Message: err.Error(),
}
}
vinList[i].ScriptSig = new(btcjson.ScriptSig) vinList[i].ScriptSig = new(btcjson.ScriptSig)
vinList[i].ScriptSig.Asm = disbuf vinList[i].ScriptSig.Asm = disbuf
vinList[i].ScriptSig.Hex = hex.EncodeToString(v.SignatureScript) vinList[i].ScriptSig.Hex = hex.EncodeToString(v.SignatureScript)
@ -718,39 +723,51 @@ func createVinList(mtx *btcwire.MsgTx) []btcjson.Vin {
vinList[i].Sequence = v.Sequence vinList[i].Sequence = v.Sequence
} }
return vinList return vinList, nil
} }
// createVoutList returns a slice of JSON objects for the outputs of the passed // createVoutList returns a slice of JSON objects for the outputs of the passed
// transaction. // transaction.
func createVoutList(mtx *btcwire.MsgTx, net btcwire.BitcoinNet) []btcjson.Vout { func createVoutList(mtx *btcwire.MsgTx, net btcwire.BitcoinNet) ([]btcjson.Vout, *btcjson.Error) {
voutList := make([]btcjson.Vout, len(mtx.TxOut)) voutList := make([]btcjson.Vout, len(mtx.TxOut))
for i, v := range mtx.TxOut { for i, v := range mtx.TxOut {
voutList[i].N = i voutList[i].N = i
voutList[i].Value = float64(v.Value) / float64(btcutil.SatoshiPerBitcoin) voutList[i].Value = float64(v.Value) / float64(btcutil.SatoshiPerBitcoin)
disbuf, err := btcscript.DisasmString(v.PkScript)
if err != nil {
return nil, &btcjson.Error{
Code: btcjson.ErrInternal.Code,
Message: err.Error(),
}
}
voutList[i].ScriptPubKey.Asm = disbuf
voutList[i].ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)
voutList[i].ScriptPubKey.Type = btcscript.NonStandardTy.String()
scriptType := btcscript.GetScriptClass(v.PkScript)
if scriptType == btcscript.NonStandardTy || scriptType == btcscript.NullDataTy {
continue
}
_, addrhash, err := btcscript.ScriptToAddrHash(v.PkScript) _, addrhash, err := btcscript.ScriptToAddrHash(v.PkScript)
if err != nil { if err != nil {
txSha, _ := mtx.TxSha() txSha, _ := mtx.TxSha()
// TODO: set and return error? // TODO: set and return error?
rpcsLog.Errorf("Error getting address hash for %v: %v", rpcsLog.Errorf("Error getting address hash for %v: %v", txSha, err)
txSha, err) continue
} }
if addr, err := btcutil.EncodeAddress(addrhash, net); err == nil { if addr, err := btcutil.EncodeAddress(addrhash, net); err == nil {
// TODO: set and return error? // TODO: set and return error?
addrList := make([]string, 1) addrList := make([]string, 1)
addrList[0] = addr addrList[0] = addr
voutList[i].ScriptPubKey.Type = scriptType.String()
voutList[i].ScriptPubKey.Addresses = addrList voutList[i].ScriptPubKey.Addresses = addrList
// TODO: replace with proper multisig handling
voutList[i].ScriptPubKey.ReqSigs = 1
} }
disbuf, _ := btcscript.DisasmString(v.PkScript)
voutList[i].ScriptPubKey.Asm = disbuf
voutList[i].ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)
voutList[i].ScriptPubKey.ReqSigs = strings.Count(disbuf, "OP_CHECKSIG")
voutList[i].ScriptPubKey.Type = btcscript.GetScriptClass(v.PkScript).String()
} }
return voutList return voutList, nil
} }
// handleDecodeRawTransaction handles decoderawtransaction commands. // handleDecodeRawTransaction handles decoderawtransaction commands.
@ -781,13 +798,22 @@ func handleDecodeRawTransaction(s *rpcServer, cmd btcjson.Cmd,
} }
txSha, _ := mtx.TxSha() txSha, _ := mtx.TxSha()
vin, err := createVinList(&mtx)
if err != nil {
return nil, err
}
vout, err := createVoutList(&mtx, s.server.btcnet)
if err != nil {
return nil, err
}
// Create and return the result. // Create and return the result.
txReply := btcjson.TxRawDecodeResult{ txReply := btcjson.TxRawDecodeResult{
Txid: txSha.String(), Txid: txSha.String(),
Version: mtx.Version, Version: mtx.Version,
Locktime: mtx.LockTime, Locktime: mtx.LockTime,
Vin: createVinList(&mtx), Vin: vin,
Vout: createVoutList(&mtx, s.server.btcnet), Vout: vout,
} }
return txReply, nil return txReply, nil
} }
@ -1107,11 +1133,20 @@ func createTxRawResult(net btcwire.BitcoinNet, txSha string, mtx *btcwire.MsgTx,
return nil, err return nil, err
} }
vin, err := createVinList(mtx)
if err != nil {
return nil, err
}
vout, err := createVoutList(mtx, net)
if err != nil {
return nil, err
}
txReply := &btcjson.TxRawResult{ txReply := &btcjson.TxRawResult{
Hex: mtxHex, Hex: mtxHex,
Txid: txSha, Txid: txSha,
Vout: createVoutList(mtx, net), Vout: vout,
Vin: createVinList(mtx), Vin: vin,
Version: mtx.Version, Version: mtx.Version,
LockTime: mtx.LockTime, LockTime: mtx.LockTime,
} }