mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
adds filteraddrs param to searchrawtransactions API
This commit is contained in:
parent
b691a222d5
commit
c7eaee6020
@ -549,12 +549,13 @@ func NewReconsiderBlockCmd(blockHash string) *ReconsiderBlockCmd {
|
|||||||
|
|
||||||
// SearchRawTransactionsCmd defines the searchrawtransactions JSON-RPC command.
|
// SearchRawTransactionsCmd defines the searchrawtransactions JSON-RPC command.
|
||||||
type SearchRawTransactionsCmd struct {
|
type SearchRawTransactionsCmd struct {
|
||||||
Address string
|
Address string
|
||||||
Verbose *int `jsonrpcdefault:"1"`
|
Verbose *int `jsonrpcdefault:"1"`
|
||||||
Skip *int `jsonrpcdefault:"0"`
|
Skip *int `jsonrpcdefault:"0"`
|
||||||
Count *int `jsonrpcdefault:"100"`
|
Count *int `jsonrpcdefault:"100"`
|
||||||
VinExtra *int `jsonrpcdefault:"0"`
|
VinExtra *int `jsonrpcdefault:"0"`
|
||||||
Reverse *bool `jsonrpcdefault:"false"`
|
Reverse *bool `jsonrpcdefault:"false"`
|
||||||
|
FilterAddrs *[]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSearchRawTransactionsCmd returns a new instance which can be used to issue a
|
// NewSearchRawTransactionsCmd returns a new instance which can be used to issue a
|
||||||
@ -562,14 +563,15 @@ type SearchRawTransactionsCmd struct {
|
|||||||
//
|
//
|
||||||
// The parameters which are pointers indicate they are optional. Passing nil
|
// The parameters which are pointers indicate they are optional. Passing nil
|
||||||
// for optional parameters will use the default value.
|
// for optional parameters will use the default value.
|
||||||
func NewSearchRawTransactionsCmd(address string, verbose, skip, count *int, vinExtra *int, reverse *bool) *SearchRawTransactionsCmd {
|
func NewSearchRawTransactionsCmd(address string, verbose, skip, count *int, vinExtra *int, reverse *bool, filterAddrs *[]string) *SearchRawTransactionsCmd {
|
||||||
return &SearchRawTransactionsCmd{
|
return &SearchRawTransactionsCmd{
|
||||||
Address: address,
|
Address: address,
|
||||||
Verbose: verbose,
|
Verbose: verbose,
|
||||||
Skip: skip,
|
Skip: skip,
|
||||||
Count: count,
|
Count: count,
|
||||||
VinExtra: vinExtra,
|
VinExtra: vinExtra,
|
||||||
Reverse: reverse,
|
Reverse: reverse,
|
||||||
|
FilterAddrs: filterAddrs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,16 +700,17 @@ func TestChainSvrCmds(t *testing.T) {
|
|||||||
return btcjson.NewCmd("searchrawtransactions", "1Address")
|
return btcjson.NewCmd("searchrawtransactions", "1Address")
|
||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewSearchRawTransactionsCmd("1Address", nil, nil, nil, nil, nil)
|
return btcjson.NewSearchRawTransactionsCmd("1Address", nil, nil, nil, nil, nil, nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address"],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address"],"id":1}`,
|
||||||
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
||||||
Address: "1Address",
|
Address: "1Address",
|
||||||
Verbose: btcjson.Int(1),
|
Verbose: btcjson.Int(1),
|
||||||
Skip: btcjson.Int(0),
|
Skip: btcjson.Int(0),
|
||||||
Count: btcjson.Int(100),
|
Count: btcjson.Int(100),
|
||||||
VinExtra: btcjson.Int(0),
|
VinExtra: btcjson.Int(0),
|
||||||
Reverse: btcjson.Bool(false),
|
Reverse: btcjson.Bool(false),
|
||||||
|
FilterAddrs: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -719,16 +720,17 @@ func TestChainSvrCmds(t *testing.T) {
|
|||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
||||||
btcjson.Int(0), nil, nil, nil, nil)
|
btcjson.Int(0), nil, nil, nil, nil, nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0],"id":1}`,
|
||||||
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
||||||
Address: "1Address",
|
Address: "1Address",
|
||||||
Verbose: btcjson.Int(0),
|
Verbose: btcjson.Int(0),
|
||||||
Skip: btcjson.Int(0),
|
Skip: btcjson.Int(0),
|
||||||
Count: btcjson.Int(100),
|
Count: btcjson.Int(100),
|
||||||
VinExtra: btcjson.Int(0),
|
VinExtra: btcjson.Int(0),
|
||||||
Reverse: btcjson.Bool(false),
|
Reverse: btcjson.Bool(false),
|
||||||
|
FilterAddrs: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -738,16 +740,17 @@ func TestChainSvrCmds(t *testing.T) {
|
|||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
||||||
btcjson.Int(0), btcjson.Int(5), nil, nil, nil)
|
btcjson.Int(0), btcjson.Int(5), nil, nil, nil, nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5],"id":1}`,
|
||||||
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
||||||
Address: "1Address",
|
Address: "1Address",
|
||||||
Verbose: btcjson.Int(0),
|
Verbose: btcjson.Int(0),
|
||||||
Skip: btcjson.Int(5),
|
Skip: btcjson.Int(5),
|
||||||
Count: btcjson.Int(100),
|
Count: btcjson.Int(100),
|
||||||
VinExtra: btcjson.Int(0),
|
VinExtra: btcjson.Int(0),
|
||||||
Reverse: btcjson.Bool(false),
|
Reverse: btcjson.Bool(false),
|
||||||
|
FilterAddrs: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -757,16 +760,17 @@ func TestChainSvrCmds(t *testing.T) {
|
|||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
||||||
btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), nil, nil)
|
btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), nil, nil, nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10],"id":1}`,
|
||||||
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
||||||
Address: "1Address",
|
Address: "1Address",
|
||||||
Verbose: btcjson.Int(0),
|
Verbose: btcjson.Int(0),
|
||||||
Skip: btcjson.Int(5),
|
Skip: btcjson.Int(5),
|
||||||
Count: btcjson.Int(10),
|
Count: btcjson.Int(10),
|
||||||
VinExtra: btcjson.Int(0),
|
VinExtra: btcjson.Int(0),
|
||||||
Reverse: btcjson.Bool(false),
|
Reverse: btcjson.Bool(false),
|
||||||
|
FilterAddrs: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -776,16 +780,17 @@ func TestChainSvrCmds(t *testing.T) {
|
|||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
||||||
btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), nil)
|
btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), nil, nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1],"id":1}`,
|
||||||
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
||||||
Address: "1Address",
|
Address: "1Address",
|
||||||
Verbose: btcjson.Int(0),
|
Verbose: btcjson.Int(0),
|
||||||
Skip: btcjson.Int(5),
|
Skip: btcjson.Int(5),
|
||||||
Count: btcjson.Int(10),
|
Count: btcjson.Int(10),
|
||||||
VinExtra: btcjson.Int(1),
|
VinExtra: btcjson.Int(1),
|
||||||
Reverse: btcjson.Bool(false),
|
Reverse: btcjson.Bool(false),
|
||||||
|
FilterAddrs: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -795,16 +800,37 @@ func TestChainSvrCmds(t *testing.T) {
|
|||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
||||||
btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), btcjson.Bool(true))
|
btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), btcjson.Bool(true), nil)
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1,true],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1,true],"id":1}`,
|
||||||
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
||||||
Address: "1Address",
|
Address: "1Address",
|
||||||
Verbose: btcjson.Int(0),
|
Verbose: btcjson.Int(0),
|
||||||
Skip: btcjson.Int(5),
|
Skip: btcjson.Int(5),
|
||||||
Count: btcjson.Int(10),
|
Count: btcjson.Int(10),
|
||||||
VinExtra: btcjson.Int(1),
|
VinExtra: btcjson.Int(1),
|
||||||
Reverse: btcjson.Bool(true),
|
Reverse: btcjson.Bool(true),
|
||||||
|
FilterAddrs: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "searchrawtransactions",
|
||||||
|
newCmd: func() (interface{}, error) {
|
||||||
|
return btcjson.NewCmd("searchrawtransactions", "1Address", 0, 5, 10, 1, true, []string{"1Address"})
|
||||||
|
},
|
||||||
|
staticCmd: func() interface{} {
|
||||||
|
return btcjson.NewSearchRawTransactionsCmd("1Address",
|
||||||
|
btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), btcjson.Bool(true), &[]string{"1Address"})
|
||||||
|
},
|
||||||
|
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1,true,["1Address"]],"id":1}`,
|
||||||
|
unmarshalled: &btcjson.SearchRawTransactionsCmd{
|
||||||
|
Address: "1Address",
|
||||||
|
Verbose: btcjson.Int(0),
|
||||||
|
Skip: btcjson.Int(5),
|
||||||
|
Count: btcjson.Int(10),
|
||||||
|
VinExtra: btcjson.Int(1),
|
||||||
|
Reverse: btcjson.Bool(true),
|
||||||
|
FilterAddrs: &[]string{"1Address"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -400,7 +400,7 @@ type TxRawResult struct {
|
|||||||
// SearchRawTransactionsResult models the data from the searchrawtransaction
|
// SearchRawTransactionsResult models the data from the searchrawtransaction
|
||||||
// command.
|
// command.
|
||||||
type SearchRawTransactionsResult struct {
|
type SearchRawTransactionsResult struct {
|
||||||
Hex string `json:"hex"`
|
Hex string `json:"hex,omitempty"`
|
||||||
Txid string `json:"txid"`
|
Txid string `json:"txid"`
|
||||||
Version int32 `json:"version"`
|
Version int32 `json:"version"`
|
||||||
LockTime uint32 `json:"locktime"`
|
LockTime uint32 `json:"locktime"`
|
||||||
|
160
rpcserver.go
160
rpcserver.go
@ -664,22 +664,41 @@ func createVinList(mtx *wire.MsgTx) []btcjson.Vin {
|
|||||||
return vinList
|
return vinList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stringInSlice returns true if string a is found in array list.
|
||||||
|
func stringInSlice(a string, list []string) bool {
|
||||||
|
for _, b := range list {
|
||||||
|
if b == a {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 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 createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params, vinExtra int) []btcjson.VinPrevOut {
|
func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params, vinExtra int, filterAddrMap map[string]struct{}) []btcjson.VinPrevOut {
|
||||||
|
// We use a dynamically sized list to accomodate address filter.
|
||||||
|
vinList := make([]btcjson.VinPrevOut, 0, len(mtx.TxIn))
|
||||||
|
|
||||||
// Coinbase transactions only have a single txin by definition.
|
// Coinbase transactions only have a single txin by definition.
|
||||||
vinList := make([]btcjson.VinPrevOut, len(mtx.TxIn))
|
|
||||||
if blockchain.IsCoinBaseTx(mtx) {
|
if blockchain.IsCoinBaseTx(mtx) {
|
||||||
|
// include tx only if filterAddrMap is empty because coinbase has no address
|
||||||
|
// and so would never match a non-empty filter.
|
||||||
|
if len(filterAddrMap) != 0 {
|
||||||
|
return vinList
|
||||||
|
}
|
||||||
|
var vinEntry btcjson.VinPrevOut
|
||||||
txIn := mtx.TxIn[0]
|
txIn := mtx.TxIn[0]
|
||||||
vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript)
|
vinEntry.Coinbase = hex.EncodeToString(txIn.SignatureScript)
|
||||||
vinList[0].Sequence = txIn.Sequence
|
vinEntry.Sequence = txIn.Sequence
|
||||||
|
vinList = append(vinList, vinEntry)
|
||||||
return vinList
|
return vinList
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup all of the referenced transactions needed to populate the
|
// Lookup all of the referenced transactions needed to populate the
|
||||||
// previous output information if requested.
|
// previous output information if requested.
|
||||||
var txStore blockchain.TxStore
|
var txStore blockchain.TxStore
|
||||||
if vinExtra != 0 {
|
if vinExtra != 0 || len(filterAddrMap) > 0 {
|
||||||
tx := btcutil.NewTx(mtx)
|
tx := btcutil.NewTx(mtx)
|
||||||
txStoreNew, err := s.server.txMemPool.fetchInputTransactions(tx, true)
|
txStoreNew, err := s.server.txMemPool.fetchInputTransactions(tx, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -687,26 +706,15 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, txIn := range mtx.TxIn {
|
for _, txIn := range mtx.TxIn {
|
||||||
|
// reset filter flag for each.
|
||||||
|
passesFilter := len(filterAddrMap) == 0
|
||||||
|
|
||||||
// The disassembled string will contain [error] inline
|
// The disassembled string will contain [error] inline
|
||||||
// if the script doesn't fully parse, so ignore the
|
// if the script doesn't fully parse, so ignore the
|
||||||
// error here.
|
// error here.
|
||||||
disbuf, _ := txscript.DisasmString(txIn.SignatureScript)
|
disbuf, _ := txscript.DisasmString(txIn.SignatureScript)
|
||||||
|
|
||||||
vinEntry := &vinList[i]
|
|
||||||
vinEntry.Txid = txIn.PreviousOutPoint.Hash.String()
|
|
||||||
vinEntry.Vout = txIn.PreviousOutPoint.Index
|
|
||||||
vinEntry.Sequence = txIn.Sequence
|
|
||||||
vinEntry.ScriptSig = &btcjson.ScriptSig{
|
|
||||||
Asm: disbuf,
|
|
||||||
Hex: hex.EncodeToString(txIn.SignatureScript),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only populate previous output information if requested and
|
|
||||||
// available.
|
|
||||||
if vinExtra == 0 || len(txStore) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
txData := txStore[txIn.PreviousOutPoint.Hash]
|
txData := txStore[txIn.PreviousOutPoint.Hash]
|
||||||
if txData == nil {
|
if txData == nil {
|
||||||
continue
|
continue
|
||||||
@ -717,20 +725,42 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
|||||||
// Ignore the error here since an error means the script
|
// Ignore the error here since an error means the script
|
||||||
// couldn't parse and there is no additional information about
|
// couldn't parse and there is no additional information about
|
||||||
// it anyways.
|
// it anyways.
|
||||||
var strAddrs []string
|
|
||||||
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
|
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
|
||||||
originTxOut.PkScript, chainParams)
|
originTxOut.PkScript, chainParams)
|
||||||
if addrs != nil {
|
|
||||||
strAddrs = make([]string, len(addrs))
|
encodedAddrs := make([]string, len(addrs))
|
||||||
for j, addr := range addrs {
|
for j, addr := range addrs {
|
||||||
strAddrs[j] = addr.EncodeAddress()
|
encodedAddrs[j] = addr.EncodeAddress()
|
||||||
|
|
||||||
|
if len(filterAddrMap) > 0 {
|
||||||
|
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
||||||
|
passesFilter = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vinEntry.PrevOut = &btcjson.PrevOut{
|
if !passesFilter {
|
||||||
Addresses: strAddrs,
|
continue
|
||||||
Value: btcutil.Amount(originTxOut.Value).ToBTC(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var vinEntry btcjson.VinPrevOut
|
||||||
|
vinEntry.Txid = txIn.PreviousOutPoint.Hash.String()
|
||||||
|
vinEntry.Vout = txIn.PreviousOutPoint.Index
|
||||||
|
vinEntry.Sequence = txIn.Sequence
|
||||||
|
vinEntry.ScriptSig = &btcjson.ScriptSig{
|
||||||
|
Asm: disbuf,
|
||||||
|
Hex: hex.EncodeToString(txIn.SignatureScript),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only populate previous output information if requested
|
||||||
|
if vinExtra != 0 {
|
||||||
|
vinEntry.PrevOut = &btcjson.PrevOut{
|
||||||
|
Addresses: encodedAddrs,
|
||||||
|
Value: btcutil.Amount(originTxOut.Value).ToBTC(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vinList = append(vinList, vinEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
return vinList
|
return vinList
|
||||||
@ -738,34 +768,47 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
|||||||
|
|
||||||
// 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 *wire.MsgTx, chainParams *chaincfg.Params) []btcjson.Vout {
|
func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap map[string]struct{}) []btcjson.Vout {
|
||||||
voutList := make([]btcjson.Vout, len(mtx.TxOut))
|
voutList := make([]btcjson.Vout, 0, len(mtx.TxOut))
|
||||||
for i, v := range mtx.TxOut {
|
for i, v := range mtx.TxOut {
|
||||||
voutList[i].N = uint32(i)
|
// reset filter flag for each.
|
||||||
voutList[i].Value = btcutil.Amount(v.Value).ToBTC()
|
passesFilter := len(filterAddrMap) == 0
|
||||||
|
|
||||||
// The disassembled string will contain [error] inline if the
|
// The disassembled string will contain [error] inline if the
|
||||||
// script doesn't fully parse, so ignore the error here.
|
// script doesn't fully parse, so ignore the error here.
|
||||||
disbuf, _ := txscript.DisasmString(v.PkScript)
|
disbuf, _ := txscript.DisasmString(v.PkScript)
|
||||||
voutList[i].ScriptPubKey.Asm = disbuf
|
|
||||||
voutList[i].ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)
|
|
||||||
|
|
||||||
// Ignore the error here since an error means the script
|
// Ignore the error here since an error means the script
|
||||||
// couldn't parse and there is no additional information about
|
// couldn't parse and there is no additional information about
|
||||||
// it anyways.
|
// it anyways.
|
||||||
scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
|
scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
|
||||||
v.PkScript, chainParams)
|
v.PkScript, chainParams)
|
||||||
voutList[i].ScriptPubKey.Type = scriptClass.String()
|
|
||||||
voutList[i].ScriptPubKey.ReqSigs = int32(reqSigs)
|
|
||||||
|
|
||||||
if addrs == nil {
|
encodedAddrs := make([]string, len(addrs))
|
||||||
voutList[i].ScriptPubKey.Addresses = nil
|
for j, addr := range addrs {
|
||||||
} else {
|
encodedAddrs[j] = addr.EncodeAddress()
|
||||||
voutList[i].ScriptPubKey.Addresses = make([]string, len(addrs))
|
|
||||||
for j, addr := range addrs {
|
if len(filterAddrMap) > 0 {
|
||||||
voutList[i].ScriptPubKey.Addresses[j] = addr.EncodeAddress()
|
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
||||||
|
passesFilter = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !passesFilter {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var vout btcjson.Vout
|
||||||
|
vout.N = uint32(i)
|
||||||
|
vout.Value = btcutil.Amount(v.Value).ToBTC()
|
||||||
|
vout.ScriptPubKey.Addresses = encodedAddrs
|
||||||
|
vout.ScriptPubKey.Asm = disbuf
|
||||||
|
vout.ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)
|
||||||
|
vout.ScriptPubKey.Type = scriptClass.String()
|
||||||
|
vout.ScriptPubKey.ReqSigs = int32(reqSigs)
|
||||||
|
|
||||||
|
voutList = append(voutList, vout)
|
||||||
}
|
}
|
||||||
|
|
||||||
return voutList
|
return voutList
|
||||||
@ -775,18 +818,24 @@ func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params) []btcjson.Vou
|
|||||||
// to a raw transaction JSON object, possibly with vin.PrevOut section.
|
// to a raw transaction JSON object, possibly with vin.PrevOut section.
|
||||||
func createSearchRawTransactionsResult(s *rpcServer, chainParams *chaincfg.Params, mtx *wire.MsgTx,
|
func createSearchRawTransactionsResult(s *rpcServer, chainParams *chaincfg.Params, mtx *wire.MsgTx,
|
||||||
txHash string, blkHeader *wire.BlockHeader, blkHash string,
|
txHash string, blkHeader *wire.BlockHeader, blkHash string,
|
||||||
blkHeight int32, chainHeight int32, vinExtra int) (*btcjson.SearchRawTransactionsResult, error) {
|
blkHeight int32, chainHeight int32, vinExtra int, filterAddrMap map[string]struct{}) (*btcjson.SearchRawTransactionsResult, error) {
|
||||||
|
|
||||||
mtxHex, err := messageToHex(mtx)
|
// omit hex if filterAddrMap are present. When filtering, typically the
|
||||||
if err != nil {
|
// goal is to reduce unnecessary bloat in the result.
|
||||||
return nil, err
|
var mtxHex string
|
||||||
|
if len(filterAddrMap) == 0 {
|
||||||
|
mtxHexTmp, err := messageToHex(mtx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mtxHex = mtxHexTmp
|
||||||
}
|
}
|
||||||
|
|
||||||
txReply := &btcjson.SearchRawTransactionsResult{
|
txReply := &btcjson.SearchRawTransactionsResult{
|
||||||
Hex: mtxHex,
|
Hex: mtxHex,
|
||||||
Txid: txHash,
|
Txid: txHash,
|
||||||
Vout: createVoutList(mtx, chainParams),
|
Vout: createVoutList(mtx, chainParams, filterAddrMap),
|
||||||
Vin: createVinListPrevOut(s, mtx, chainParams, vinExtra),
|
Vin: createVinListPrevOut(s, mtx, chainParams, vinExtra, filterAddrMap),
|
||||||
Version: mtx.Version,
|
Version: mtx.Version,
|
||||||
LockTime: mtx.LockTime,
|
LockTime: mtx.LockTime,
|
||||||
}
|
}
|
||||||
@ -816,7 +865,7 @@ func createTxRawResult(chainParams *chaincfg.Params, mtx *wire.MsgTx,
|
|||||||
txReply := &btcjson.TxRawResult{
|
txReply := &btcjson.TxRawResult{
|
||||||
Hex: mtxHex,
|
Hex: mtxHex,
|
||||||
Txid: txHash,
|
Txid: txHash,
|
||||||
Vout: createVoutList(mtx, chainParams),
|
Vout: createVoutList(mtx, chainParams, nil),
|
||||||
Vin: createVinList(mtx),
|
Vin: createVinList(mtx),
|
||||||
Version: mtx.Version,
|
Version: mtx.Version,
|
||||||
LockTime: mtx.LockTime,
|
LockTime: mtx.LockTime,
|
||||||
@ -861,7 +910,7 @@ func handleDecodeRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan
|
|||||||
Version: mtx.Version,
|
Version: mtx.Version,
|
||||||
Locktime: mtx.LockTime,
|
Locktime: mtx.LockTime,
|
||||||
Vin: createVinList(&mtx),
|
Vin: createVinList(&mtx),
|
||||||
Vout: createVoutList(&mtx, s.server.chainParams),
|
Vout: createVoutList(&mtx, s.server.chainParams, nil),
|
||||||
}
|
}
|
||||||
return txReply, nil
|
return txReply, nil
|
||||||
}
|
}
|
||||||
@ -3175,8 +3224,17 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan
|
|||||||
blkHeight = txReply.Height
|
blkHeight = txReply.Height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// c.FilterAddrs can be nil, empty or non-empty. Here we normalize that
|
||||||
|
// to a non-nil array (empty or non-empty) to avoid future nil checks.
|
||||||
|
filterAddrMap := make(map[string]struct{})
|
||||||
|
if c.FilterAddrs != nil && len(*c.FilterAddrs) > 0 {
|
||||||
|
for _, addr := range *c.FilterAddrs {
|
||||||
|
filterAddrMap[addr] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rawTxn, err := createSearchRawTransactionsResult(s, s.server.chainParams, mtx,
|
rawTxn, err := createSearchRawTransactionsResult(s, s.server.chainParams, mtx,
|
||||||
txHash, blkHeader, blkHashStr, blkHeight, maxIdx, *c.VinExtra)
|
txHash, blkHeader, blkHashStr, blkHeight, maxIdx, *c.VinExtra, filterAddrMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -472,6 +472,7 @@ var helpDescsEnUS = map[string]string{
|
|||||||
"searchrawtransactions-count": "The maximum number of transactions to return",
|
"searchrawtransactions-count": "The maximum number of transactions to return",
|
||||||
"searchrawtransactions-vinextra": "Specify that extra data from previous output will be returned in vin",
|
"searchrawtransactions-vinextra": "Specify that extra data from previous output will be returned in vin",
|
||||||
"searchrawtransactions-reverse": "Specifies that the transactions should be returned in reverse chronological order",
|
"searchrawtransactions-reverse": "Specifies that the transactions should be returned in reverse chronological order",
|
||||||
|
"searchrawtransactions-filteraddrs": "Address list. Only inputs or outputs with matching address will be returned",
|
||||||
"searchrawtransactions--result0": "Hex-encoded serialized transaction",
|
"searchrawtransactions--result0": "Hex-encoded serialized transaction",
|
||||||
|
|
||||||
// SendRawTransactionCmd help.
|
// SendRawTransactionCmd help.
|
||||||
|
Loading…
Reference in New Issue
Block a user