rpcserver: Add filteraddrs param to srt API.
Contains the following upstream commits: -365b1bd156- Previously cherry-picked so it is a NOOP -b691a222d5- Reverted because Decred uses a different signature algorithm -c7eaee6020In addition to the normal required changes for syncing, the following changes have been made in order to facilitate integration into Decred: - Rework the code which extracts stake submission outputs a bit to be a little more efficient and to better fit with the code being merged
This commit is contained in:
commit
3799575c9c
@ -587,12 +587,13 @@ func NewReconsiderBlockCmd(blockHash string) *ReconsiderBlockCmd {
|
||||
|
||||
// SearchRawTransactionsCmd defines the searchrawtransactions JSON-RPC command.
|
||||
type SearchRawTransactionsCmd struct {
|
||||
Address string
|
||||
Verbose *int `jsonrpcdefault:"1"`
|
||||
Skip *int `jsonrpcdefault:"0"`
|
||||
Count *int `jsonrpcdefault:"100"`
|
||||
VinExtra *int `jsonrpcdefault:"0"`
|
||||
Reverse *bool `jsonrpcdefault:"false"`
|
||||
Address string
|
||||
Verbose *int `jsonrpcdefault:"1"`
|
||||
Skip *int `jsonrpcdefault:"0"`
|
||||
Count *int `jsonrpcdefault:"100"`
|
||||
VinExtra *int `jsonrpcdefault:"0"`
|
||||
Reverse *bool `jsonrpcdefault:"false"`
|
||||
FilterAddrs *[]string
|
||||
}
|
||||
|
||||
// NewSearchRawTransactionsCmd returns a new instance which can be used to issue a
|
||||
@ -600,14 +601,15 @@ type SearchRawTransactionsCmd struct {
|
||||
//
|
||||
// The parameters which are pointers indicate they are optional. Passing nil
|
||||
// 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{
|
||||
Address: address,
|
||||
Verbose: verbose,
|
||||
Skip: skip,
|
||||
Count: count,
|
||||
VinExtra: vinExtra,
|
||||
Reverse: reverse,
|
||||
Address: address,
|
||||
Verbose: verbose,
|
||||
Skip: skip,
|
||||
Count: count,
|
||||
VinExtra: vinExtra,
|
||||
Reverse: reverse,
|
||||
FilterAddrs: filterAddrs,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2015 The Decred developers
|
||||
// Copyright (c) 2016 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -714,16 +714,17 @@ func TestChainSvrCmds(t *testing.T) {
|
||||
return dcrjson.NewCmd("searchrawtransactions", "1Address")
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address", nil, nil, nil, nil, nil)
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address", nil, nil, nil, nil, nil, nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address"],"id":1}`,
|
||||
unmarshalled: &dcrjson.SearchRawTransactionsCmd{
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(1),
|
||||
Skip: dcrjson.Int(0),
|
||||
Count: dcrjson.Int(100),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(1),
|
||||
Skip: dcrjson.Int(0),
|
||||
Count: dcrjson.Int(100),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
FilterAddrs: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -733,16 +734,17 @@ func TestChainSvrCmds(t *testing.T) {
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address",
|
||||
dcrjson.Int(0), nil, nil, nil, nil)
|
||||
dcrjson.Int(0), nil, nil, nil, nil, nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0],"id":1}`,
|
||||
unmarshalled: &dcrjson.SearchRawTransactionsCmd{
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(0),
|
||||
Count: dcrjson.Int(100),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(0),
|
||||
Count: dcrjson.Int(100),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
FilterAddrs: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -752,16 +754,17 @@ func TestChainSvrCmds(t *testing.T) {
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address",
|
||||
dcrjson.Int(0), dcrjson.Int(5), nil, nil, nil)
|
||||
dcrjson.Int(0), dcrjson.Int(5), nil, nil, nil, nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5],"id":1}`,
|
||||
unmarshalled: &dcrjson.SearchRawTransactionsCmd{
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(100),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(100),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
FilterAddrs: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -771,16 +774,17 @@ func TestChainSvrCmds(t *testing.T) {
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address",
|
||||
dcrjson.Int(0), dcrjson.Int(5), dcrjson.Int(10), nil, nil)
|
||||
dcrjson.Int(0), dcrjson.Int(5), dcrjson.Int(10), nil, nil, nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10],"id":1}`,
|
||||
unmarshalled: &dcrjson.SearchRawTransactionsCmd{
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(10),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(10),
|
||||
VinExtra: dcrjson.Int(0),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
FilterAddrs: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -790,16 +794,17 @@ func TestChainSvrCmds(t *testing.T) {
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address",
|
||||
dcrjson.Int(0), dcrjson.Int(5), dcrjson.Int(10), dcrjson.Int(1), nil)
|
||||
dcrjson.Int(0), dcrjson.Int(5), dcrjson.Int(10), dcrjson.Int(1), nil, nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1],"id":1}`,
|
||||
unmarshalled: &dcrjson.SearchRawTransactionsCmd{
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(10),
|
||||
VinExtra: dcrjson.Int(1),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(10),
|
||||
VinExtra: dcrjson.Int(1),
|
||||
Reverse: dcrjson.Bool(false),
|
||||
FilterAddrs: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -809,16 +814,39 @@ func TestChainSvrCmds(t *testing.T) {
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address",
|
||||
dcrjson.Int(0), dcrjson.Int(5), dcrjson.Int(10), dcrjson.Int(1), dcrjson.Bool(true))
|
||||
dcrjson.Int(0), dcrjson.Int(5), dcrjson.Int(10),
|
||||
dcrjson.Int(1), dcrjson.Bool(true), nil)
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1,true],"id":1}`,
|
||||
unmarshalled: &dcrjson.SearchRawTransactionsCmd{
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(10),
|
||||
VinExtra: dcrjson.Int(1),
|
||||
Reverse: dcrjson.Bool(true),
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(10),
|
||||
VinExtra: dcrjson.Int(1),
|
||||
Reverse: dcrjson.Bool(true),
|
||||
FilterAddrs: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "searchrawtransactions",
|
||||
newCmd: func() (interface{}, error) {
|
||||
return dcrjson.NewCmd("searchrawtransactions", "1Address", 0, 5, 10, 1, true, []string{"1Address"})
|
||||
},
|
||||
staticCmd: func() interface{} {
|
||||
return dcrjson.NewSearchRawTransactionsCmd("1Address",
|
||||
dcrjson.Int(0), dcrjson.Int(5), dcrjson.Int(10),
|
||||
dcrjson.Int(1), dcrjson.Bool(true), &[]string{"1Address"})
|
||||
},
|
||||
marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1,true,["1Address"]],"id":1}`,
|
||||
unmarshalled: &dcrjson.SearchRawTransactionsCmd{
|
||||
Address: "1Address",
|
||||
Verbose: dcrjson.Int(0),
|
||||
Skip: dcrjson.Int(5),
|
||||
Count: dcrjson.Int(10),
|
||||
VinExtra: dcrjson.Int(1),
|
||||
Reverse: dcrjson.Bool(true),
|
||||
FilterAddrs: &[]string{"1Address"},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -457,7 +457,7 @@ type TxRawResult struct {
|
||||
// SearchRawTransactionsResult models the data from the searchrawtransaction
|
||||
// command.
|
||||
type SearchRawTransactionsResult struct {
|
||||
Hex string `json:"hex"`
|
||||
Hex string `json:"hex,omitempty"`
|
||||
Txid string `json:"txid"`
|
||||
Version int32 `json:"version"`
|
||||
LockTime uint32 `json:"locktime"`
|
||||
|
||||
247
rpcserver.go
247
rpcserver.go
@ -1355,22 +1355,43 @@ func createVinList(mtx *wire.MsgTx) []dcrjson.Vin {
|
||||
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
|
||||
// transaction.
|
||||
func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params, vinExtra int) []dcrjson.VinPrevOut {
|
||||
func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params,
|
||||
vinExtra int, filterAddrMap map[string]struct{}) []dcrjson.VinPrevOut {
|
||||
|
||||
// We use a dynamically sized list to accomodate address filter.
|
||||
vinList := make([]dcrjson.VinPrevOut, 0, len(mtx.TxIn))
|
||||
|
||||
// Coinbase transactions only have a single txin by definition.
|
||||
vinList := make([]dcrjson.VinPrevOut, len(mtx.TxIn))
|
||||
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 dcrjson.VinPrevOut
|
||||
txIn := mtx.TxIn[0]
|
||||
vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript)
|
||||
vinList[0].Sequence = txIn.Sequence
|
||||
vinEntry.Coinbase = hex.EncodeToString(txIn.SignatureScript)
|
||||
vinEntry.Sequence = txIn.Sequence
|
||||
vinList = append(vinList, vinEntry)
|
||||
return vinList
|
||||
}
|
||||
|
||||
// Lookup all of the referenced transactions needed to populate the
|
||||
// previous output information if requested.
|
||||
var txStore blockchain.TxStore
|
||||
if vinExtra != 0 {
|
||||
if vinExtra != 0 || len(filterAddrMap) > 0 {
|
||||
tx := dcrutil.NewTx(mtx)
|
||||
txStoreNew, err := s.server.txMemPool.fetchInputTransactions(tx, true)
|
||||
if err == nil {
|
||||
@ -1378,13 +1399,43 @@ 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
|
||||
// if the script doesn't fully parse, so ignore the
|
||||
// error here.
|
||||
disbuf, _ := txscript.DisasmString(txIn.SignatureScript)
|
||||
|
||||
vinEntry := &vinList[i]
|
||||
txData := txStore[txIn.PreviousOutPoint.Hash]
|
||||
if txData == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
originTxOut := txData.Tx.MsgTx().TxOut[txIn.PreviousOutPoint.Index]
|
||||
|
||||
// Ignore the error here since an error means the script
|
||||
// couldn't parse and there is no additional information about
|
||||
// it anyways.
|
||||
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
|
||||
txscript.DefaultScriptVersion, originTxOut.PkScript, chainParams)
|
||||
encodedAddrs := make([]string, len(addrs))
|
||||
for j, addr := range addrs {
|
||||
encodedAddrs[j] = addr.EncodeAddress()
|
||||
|
||||
if len(filterAddrMap) > 0 {
|
||||
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
||||
passesFilter = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !passesFilter {
|
||||
continue
|
||||
}
|
||||
|
||||
var vinEntry dcrjson.VinPrevOut
|
||||
vinEntry.Txid = txIn.PreviousOutPoint.Hash.String()
|
||||
vinEntry.Vout = txIn.PreviousOutPoint.Index
|
||||
vinEntry.Tree = txIn.PreviousOutPoint.Tree
|
||||
@ -1405,35 +1456,15 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
||||
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]
|
||||
if txData == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
originTxOut := txData.Tx.MsgTx().TxOut[txIn.PreviousOutPoint.Index]
|
||||
|
||||
// Ignore the error here since an error means the script
|
||||
// couldn't parse and there is no additional information about
|
||||
// it anyways.
|
||||
var strAddrs []string
|
||||
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
|
||||
txscript.DefaultScriptVersion, originTxOut.PkScript, chainParams)
|
||||
if addrs != nil {
|
||||
strAddrs = make([]string, len(addrs))
|
||||
for j, addr := range addrs {
|
||||
strAddrs[j] = addr.EncodeAddress()
|
||||
// Only populate previous output information if requested
|
||||
if vinExtra != 0 {
|
||||
vinEntry.PrevOut = &dcrjson.PrevOut{
|
||||
Addresses: encodedAddrs,
|
||||
Value: dcrutil.Amount(originTxOut.Value).ToCoin(),
|
||||
}
|
||||
}
|
||||
|
||||
vinEntry.PrevOut = &dcrjson.PrevOut{
|
||||
Addresses: strAddrs,
|
||||
Value: dcrutil.Amount(originTxOut.Value).ToCoin(),
|
||||
}
|
||||
vinList = append(vinList, vinEntry)
|
||||
}
|
||||
|
||||
return vinList
|
||||
@ -1441,62 +1472,86 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
||||
|
||||
// createVoutList returns a slice of JSON objects for the outputs of the passed
|
||||
// transaction.
|
||||
func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params) []dcrjson.Vout {
|
||||
func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params,
|
||||
filterAddrMap map[string]struct{}) []dcrjson.Vout {
|
||||
|
||||
txType := stake.DetermineTxType(dcrutil.NewTx(mtx))
|
||||
voutList := make([]dcrjson.Vout, len(mtx.TxOut))
|
||||
voutList := make([]dcrjson.Vout, 0, len(mtx.TxOut))
|
||||
for i, v := range mtx.TxOut {
|
||||
voutList[i].N = uint32(i)
|
||||
voutList[i].Value = dcrutil.Amount(v.Value).ToCoin()
|
||||
voutList[i].Version = v.Version
|
||||
// reset filter flag for each.
|
||||
passesFilter := len(filterAddrMap) == 0
|
||||
|
||||
// The disassembled string will contain [error] inline if the
|
||||
// script doesn't fully parse, so ignore the error here.
|
||||
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
|
||||
// couldn't parse and there is no additional information about
|
||||
// it anyways.
|
||||
scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
|
||||
v.Version, v.PkScript, chainParams)
|
||||
voutList[i].ScriptPubKey.Type = scriptClass.String()
|
||||
voutList[i].ScriptPubKey.ReqSigs = int32(reqSigs)
|
||||
|
||||
if addrs == nil {
|
||||
voutList[i].ScriptPubKey.Addresses = nil
|
||||
|
||||
// Decode commitment outputs for tickets and set the
|
||||
// type correctly.
|
||||
if txType == stake.TxTypeSStx && (i > 0) && (i%2 != 0) {
|
||||
addr, err := stake.AddrFromSStxPkScrCommitment(v.PkScript,
|
||||
chainParams)
|
||||
if err != nil {
|
||||
rpcsLog.Warnf("failed to decode ticket commitment addr "+
|
||||
"output for tx hash %v, output idx %v", mtx.TxSha(),
|
||||
i)
|
||||
continue
|
||||
}
|
||||
amt, err := stake.AmountFromSStxPkScrCommitment(v.PkScript)
|
||||
if err != nil {
|
||||
rpcsLog.Warnf("failed to decode ticket commitment amt "+
|
||||
"output for tx hash %v, output idx %v", mtx.TxSha(),
|
||||
i)
|
||||
continue
|
||||
}
|
||||
amtCoin := amt.ToCoin()
|
||||
|
||||
voutList[i].ScriptPubKey.Type = sstxCommitmentString
|
||||
voutList[i].ScriptPubKey.Addresses = make([]string, 1)
|
||||
voutList[i].ScriptPubKey.Addresses[0] = addr.EncodeAddress()
|
||||
voutList[i].ScriptPubKey.CommitAmt = &amtCoin
|
||||
// Attempt to extract addresses from the public key script. In
|
||||
// the case of stake submission transactions, the odd outputs
|
||||
// contain a commitment address, so detect that case
|
||||
// accordingly.
|
||||
var addrs []dcrutil.Address
|
||||
var scriptClass string
|
||||
var reqSigs int
|
||||
var commitAmt *dcrutil.Amount
|
||||
if txType == stake.TxTypeSStx && (i%2 != 0) {
|
||||
scriptClass = sstxCommitmentString
|
||||
addr, err := stake.AddrFromSStxPkScrCommitment(v.PkScript,
|
||||
chainParams)
|
||||
if err != nil {
|
||||
rpcsLog.Warnf("failed to decode ticket "+
|
||||
"commitment addr output for tx hash "+
|
||||
"%v, output idx %v", mtx.TxSha(), i)
|
||||
} else {
|
||||
addrs = []dcrutil.Address{addr}
|
||||
}
|
||||
amt, err := stake.AmountFromSStxPkScrCommitment(v.PkScript)
|
||||
if err != nil {
|
||||
rpcsLog.Warnf("failed to decode ticket "+
|
||||
"commitment amt output for tx hash %v"+
|
||||
", output idx %v", mtx.TxSha(), i)
|
||||
} else {
|
||||
commitAmt = &amt
|
||||
}
|
||||
} else {
|
||||
voutList[i].ScriptPubKey.Addresses = make([]string, len(addrs))
|
||||
for j, addr := range addrs {
|
||||
voutList[i].ScriptPubKey.Addresses[j] = addr.EncodeAddress()
|
||||
// Ignore the error here since an error means the script
|
||||
// couldn't parse and there is no additional information
|
||||
// about it anyways.
|
||||
var sc txscript.ScriptClass
|
||||
sc, addrs, reqSigs, _ = txscript.ExtractPkScriptAddrs(
|
||||
v.Version, v.PkScript, chainParams)
|
||||
scriptClass = sc.String()
|
||||
}
|
||||
|
||||
encodedAddrs := make([]string, len(addrs))
|
||||
for j, addr := range addrs {
|
||||
encodedAddrs[j] = addr.EncodeAddress()
|
||||
|
||||
if len(filterAddrMap) > 0 {
|
||||
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
||||
passesFilter = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !passesFilter {
|
||||
continue
|
||||
}
|
||||
|
||||
var vout dcrjson.Vout
|
||||
voutSPK := &vout.ScriptPubKey
|
||||
vout.N = uint32(i)
|
||||
vout.Value = dcrutil.Amount(v.Value).ToCoin()
|
||||
vout.Version = v.Version
|
||||
voutSPK.Addresses = encodedAddrs
|
||||
voutSPK.Asm = disbuf
|
||||
voutSPK.Hex = hex.EncodeToString(v.PkScript)
|
||||
voutSPK.Type = scriptClass
|
||||
voutSPK.ReqSigs = int32(reqSigs)
|
||||
if commitAmt != nil {
|
||||
voutSPK.CommitAmt = dcrjson.Float64(commitAmt.ToCoin())
|
||||
}
|
||||
|
||||
voutList = append(voutList, vout)
|
||||
}
|
||||
|
||||
return voutList
|
||||
@ -1506,19 +1561,25 @@ func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params) []dcrjson.Vou
|
||||
// to a raw transaction JSON object, possibly with vin.PrevOut section.
|
||||
func createSearchRawTransactionsResult(s *rpcServer, chainParams *chaincfg.Params,
|
||||
mtx *wire.MsgTx, txHash string, blkHeader *wire.BlockHeader, blkHash string,
|
||||
blkHeight int64, chainHeight int64,
|
||||
vinExtra int) (*dcrjson.SearchRawTransactionsResult, error) {
|
||||
blkHeight int64, chainHeight int64, vinExtra int,
|
||||
filterAddrMap map[string]struct{}) (*dcrjson.SearchRawTransactionsResult, error) {
|
||||
|
||||
mtxHex, err := messageToHex(mtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// omit hex if filterAddrMap are present. When filtering, typically the
|
||||
// goal is to reduce unnecessary bloat in the result.
|
||||
var mtxHex string
|
||||
if len(filterAddrMap) == 0 {
|
||||
mtxHexTmp, err := messageToHex(mtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mtxHex = mtxHexTmp
|
||||
}
|
||||
|
||||
txReply := &dcrjson.SearchRawTransactionsResult{
|
||||
Hex: mtxHex,
|
||||
Txid: txHash,
|
||||
Vout: createVoutList(mtx, chainParams),
|
||||
Vin: createVinListPrevOut(s, mtx, chainParams, vinExtra),
|
||||
Vout: createVoutList(mtx, chainParams, filterAddrMap),
|
||||
Vin: createVinListPrevOut(s, mtx, chainParams, vinExtra, filterAddrMap),
|
||||
Version: mtx.Version,
|
||||
LockTime: mtx.LockTime,
|
||||
}
|
||||
@ -1549,7 +1610,7 @@ func createTxRawResult(chainParams *chaincfg.Params, mtx *wire.MsgTx,
|
||||
txReply := &dcrjson.TxRawResult{
|
||||
Hex: mtxHex,
|
||||
Txid: txHash,
|
||||
Vout: createVoutList(mtx, chainParams),
|
||||
Vout: createVoutList(mtx, chainParams, nil),
|
||||
Vin: createVinList(mtx),
|
||||
Version: mtx.Version,
|
||||
LockTime: mtx.LockTime,
|
||||
@ -1598,7 +1659,7 @@ func handleDecodeRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan
|
||||
Locktime: mtx.LockTime,
|
||||
Expiry: mtx.Expiry,
|
||||
Vin: createVinList(&mtx),
|
||||
Vout: createVoutList(&mtx, s.server.chainParams),
|
||||
Vout: createVoutList(&mtx, s.server.chainParams, nil),
|
||||
}
|
||||
return txReply, nil
|
||||
}
|
||||
@ -4835,8 +4896,18 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{},
|
||||
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, txHash, blkHeader, blkHashStr, blkHeight, maxIdx, *c.VinExtra)
|
||||
mtx, txHash, blkHeader, blkHashStr, blkHeight, maxIdx,
|
||||
*c.VinExtra, filterAddrMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -592,6 +592,7 @@ var helpDescsEnUS = map[string]string{
|
||||
"searchrawtransactions-count": "The maximum number of transactions to return",
|
||||
"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-filteraddrs": "Address list. Only inputs or outputs with matching address will be returned",
|
||||
"searchrawtransactions--result0": "Hex-encoded serialized transaction",
|
||||
|
||||
// SendRawTransactionCmd help.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user