From 0b50802d52cdb7e5560ea6ff3a453b7378e3d5f7 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 29 Aug 2017 20:40:19 -0500 Subject: [PATCH] btcjson/rpcserver: Encode witness stack as slice. The modifies the encoding of witness stacks in JSON responses to use a slice of strings instead of a single space-separated string for compatibility with Core. --- btcjson/chainsvrresults.go | 14 +++++++------- rpcserver.go | 39 +++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 9af1d3994..33d54d385 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -317,7 +317,7 @@ type Vin struct { Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` Sequence uint32 `json:"sequence"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` } // IsCoinBase returns a bool to show if a Vin is a Coinbase one or not. @@ -335,9 +335,9 @@ func (v *Vin) HasWitness() bool { func (v *Vin) MarshalJSON() ([]byte, error) { if v.IsCoinBase() { coinbaseStruct := struct { - Coinbase string `json:"coinbase"` - Sequence uint32 `json:"sequence"` - Witness string `json:"witness,omitempty"` + Coinbase string `json:"coinbase"` + Sequence uint32 `json:"sequence"` + Witness []string `json:"witness,omitempty"` }{ Coinbase: v.Coinbase, Sequence: v.Sequence, @@ -351,7 +351,7 @@ func (v *Vin) MarshalJSON() ([]byte, error) { Txid string `json:"txid"` Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` Sequence uint32 `json:"sequence"` }{ Txid: v.Txid, @@ -389,7 +389,7 @@ type VinPrevOut struct { Txid string `json:"txid"` Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` PrevOut *PrevOut `json:"prevOut"` Sequence uint32 `json:"sequence"` } @@ -423,7 +423,7 @@ func (v *VinPrevOut) MarshalJSON() ([]byte, error) { Txid string `json:"txid"` Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` PrevOut *PrevOut `json:"prevOut,omitempty"` Sequence uint32 `json:"sequence"` }{ diff --git a/rpcserver.go b/rpcserver.go index 602e793b9..db4dece8a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -629,6 +629,23 @@ func handleDebugLevel(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return "Done.", nil } +// witnessToHex formats the passed witness stack as a slice of hex-encoded +// strings to be used in a JSON response. +func witnessToHex(witness wire.TxWitness) []string { + // Ensure nil is returned when there are no entries versus an empty + // slice so it can properly be omitted as necessary. + if len(witness) == 0 { + return nil + } + + result := make([]string, 0, len(witness)) + for _, wit := range witness { + result = append(result, hex.EncodeToString(wit)) + } + + return result +} + // createVinList returns a slice of JSON objects for the inputs of the passed // transaction. func createVinList(mtx *wire.MsgTx) []btcjson.Vin { @@ -638,7 +655,7 @@ func createVinList(mtx *wire.MsgTx) []btcjson.Vin { txIn := mtx.TxIn[0] vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript) vinList[0].Sequence = txIn.Sequence - vinList[0].Witness = witnessToSring(txIn.Witness) + vinList[0].Witness = witnessToHex(txIn.Witness) return vinList } @@ -658,29 +675,13 @@ func createVinList(mtx *wire.MsgTx) []btcjson.Vin { } if mtx.HasWitness() { - vinEntry.Witness = witnessToSring(txIn.Witness) + vinEntry.Witness = witnessToHex(txIn.Witness) } } return vinList } -// witnessToSring formats the passed witness stack as a string to be used -// within a JSON response. The witness is encoded as a single string with -// spaces separating each witness element. -func witnessToSring(witness wire.TxWitness) string { - var b bytes.Buffer - for i, wit := range witness { - if i > 0 { - b.WriteString(" ") - } - - b.WriteString(hex.EncodeToString(wit)) - } - - return b.String() -} - // createVoutList returns a slice of JSON objects for the outputs of the passed // transaction. func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap map[string]struct{}) []btcjson.Vout { @@ -2852,7 +2853,7 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P } if len(txIn.Witness) != 0 { - vinEntry.Witness = witnessToSring(txIn.Witness) + vinEntry.Witness = witnessToHex(txIn.Witness) } // Add the entry to the list now if it already passed the filter