mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
Update for recent btcscript API changes.
This commit changes all code which deals with extracting addresses from scripts to use the btcscript API ExtractPkScriptAddrs which in turn makes use of the new btcutil.Address interface. This provides much cleaner code for dealing with arbitrary script destinations which is extensible without having to churn the APIs if new destination types are added.
This commit is contained in:
parent
96ded50f6b
commit
462bc5a031
46
rpcserver.go
46
rpcserver.go
@ -630,26 +630,18 @@ func createVoutList(mtx *btcwire.MsgTx, net btcwire.BitcoinNet) ([]btcjson.Vout,
|
|||||||
voutList[i].ScriptPubKey.Asm = disbuf
|
voutList[i].ScriptPubKey.Asm = disbuf
|
||||||
voutList[i].ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)
|
voutList[i].ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)
|
||||||
|
|
||||||
scriptType, reqSigs, hashes := btcscript.CalcPkScriptAddrHashes(v.PkScript)
|
// Ignore the error here since an error means the script
|
||||||
voutList[i].ScriptPubKey.Type = scriptType.String()
|
// couldn't parse and there is no additional information about
|
||||||
|
// it anyways.
|
||||||
|
scriptClass, addrs, reqSigs, _ := btcscript.ExtractPkScriptAddrs(v.PkScript, net)
|
||||||
|
voutList[i].ScriptPubKey.Type = scriptClass.String()
|
||||||
voutList[i].ScriptPubKey.ReqSigs = reqSigs
|
voutList[i].ScriptPubKey.ReqSigs = reqSigs
|
||||||
|
|
||||||
if hashes == nil {
|
if addrs == nil {
|
||||||
voutList[i].ScriptPubKey.Addresses = nil
|
voutList[i].ScriptPubKey.Addresses = nil
|
||||||
} else {
|
} else {
|
||||||
voutList[i].ScriptPubKey.Addresses = make([]string, len(hashes))
|
voutList[i].ScriptPubKey.Addresses = make([]string, len(addrs))
|
||||||
for j := 0; j < len(hashes); j++ {
|
for j, addr := range addrs {
|
||||||
var addr btcutil.Address
|
|
||||||
if scriptType == btcscript.ScriptHashTy {
|
|
||||||
addr, err = btcutil.NewAddressScriptHash(hashes[j], net)
|
|
||||||
} else {
|
|
||||||
addr, err = btcutil.NewAddressPubKeyHash(hashes[j], net)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
// hash will always be 20 bytes, so the only
|
|
||||||
// possible error is from an invalid network.
|
|
||||||
return nil, errors.New("Cannot create address with invalid network.")
|
|
||||||
}
|
|
||||||
voutList[i].ScriptPubKey.Addresses[j] = addr.EncodeAddress()
|
voutList[i].ScriptPubKey.Addresses[j] = addr.EncodeAddress()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -724,21 +716,13 @@ func handleDecodeScript(s *rpcServer, cmd btcjson.Cmd) (interface{}, error) {
|
|||||||
disbuf, _ := btcscript.DisasmString(script)
|
disbuf, _ := btcscript.DisasmString(script)
|
||||||
|
|
||||||
// Get information about the script.
|
// Get information about the script.
|
||||||
// TODO(davec): The btcscript CalcPkScriptAddrHashes function should
|
// Ignore the error here since an error means the script couldn't parse
|
||||||
// be changed to return btcutil.Address.
|
// and there is no additinal information about it anyways.
|
||||||
net := s.server.btcnet
|
net := s.server.btcnet
|
||||||
scriptType, reqSigs, hashes := btcscript.CalcPkScriptAddrHashes(script)
|
scriptClass, addrs, reqSigs, _ := btcscript.ExtractPkScriptAddrs(script, net)
|
||||||
addresses := make([]string, len(hashes))
|
addresses := make([]string, len(addrs))
|
||||||
for i, hash := range hashes {
|
for i, addr := range addrs {
|
||||||
var addr btcutil.Address
|
addresses[i] = addr.EncodeAddress()
|
||||||
if scriptType == btcscript.ScriptHashTy {
|
|
||||||
addr, err = btcutil.NewAddressScriptHash(hash, net)
|
|
||||||
} else {
|
|
||||||
addr, err = btcutil.NewAddressPubKeyHash(hash, net)
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
addresses[i] = addr.EncodeAddress()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the script itself to a pay-to-script-hash address.
|
// Convert the script itself to a pay-to-script-hash address.
|
||||||
@ -754,7 +738,7 @@ func handleDecodeScript(s *rpcServer, cmd btcjson.Cmd) (interface{}, error) {
|
|||||||
reply := btcjson.DecodeScriptResult{
|
reply := btcjson.DecodeScriptResult{
|
||||||
Asm: disbuf,
|
Asm: disbuf,
|
||||||
ReqSigs: reqSigs,
|
ReqSigs: reqSigs,
|
||||||
Type: scriptType.String(),
|
Type: scriptClass.String(),
|
||||||
Addresses: addresses,
|
Addresses: addresses,
|
||||||
P2sh: p2sh.EncodeAddress(),
|
P2sh: p2sh.EncodeAddress(),
|
||||||
}
|
}
|
||||||
|
224
rpcwebsocket.go
224
rpcwebsocket.go
@ -65,7 +65,7 @@ type notificationCtx struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddTxRequest adds the request context for new transaction notifications.
|
// AddTxRequest adds the request context for new transaction notifications.
|
||||||
func (r *wsContext) AddTxRequest(walletNotification chan []byte, rc *requestContexts, addrhash string, id interface{}) {
|
func (r *wsContext) AddTxRequest(walletNotification chan []byte, rc *requestContexts, addr string, id interface{}) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
|
|
||||||
@ -75,19 +75,19 @@ func (r *wsContext) AddTxRequest(walletNotification chan []byte, rc *requestCont
|
|||||||
rc: rc,
|
rc: rc,
|
||||||
}
|
}
|
||||||
|
|
||||||
clist, ok := r.txNotifications[addrhash]
|
clist, ok := r.txNotifications[addr]
|
||||||
if !ok {
|
if !ok {
|
||||||
clist = list.New()
|
clist = list.New()
|
||||||
r.txNotifications[addrhash] = clist
|
r.txNotifications[addr] = clist
|
||||||
}
|
}
|
||||||
|
|
||||||
clist.PushBack(nc)
|
clist.PushBack(nc)
|
||||||
|
|
||||||
rc.txRequests[addrhash] = id
|
rc.txRequests[addr] = id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *wsContext) removeGlobalTxRequest(walletNotification chan []byte, addrhash string) {
|
func (r *wsContext) removeGlobalTxRequest(walletNotification chan []byte, addr string) {
|
||||||
clist := r.txNotifications[addrhash]
|
clist := r.txNotifications[addr]
|
||||||
var enext *list.Element
|
var enext *list.Element
|
||||||
for e := clist.Front(); e != nil; e = enext {
|
for e := clist.Front(); e != nil; e = enext {
|
||||||
enext = e.Next()
|
enext = e.Next()
|
||||||
@ -99,7 +99,7 @@ func (r *wsContext) removeGlobalTxRequest(walletNotification chan []byte, addrha
|
|||||||
}
|
}
|
||||||
|
|
||||||
if clist.Len() == 0 {
|
if clist.Len() == 0 {
|
||||||
delete(r.txNotifications, addrhash)
|
delete(r.txNotifications, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,8 +351,8 @@ func handleNotifyNewTXs(s *rpcServer, cmd btcjson.Cmd,
|
|||||||
return fmt.Errorf("address is not P2PKH: %v", addr.EncodeAddress())
|
return fmt.Errorf("address is not P2PKH: %v", addr.EncodeAddress())
|
||||||
}
|
}
|
||||||
|
|
||||||
s.ws.AddTxRequest(walletNotification, rc,
|
s.ws.AddTxRequest(walletNotification, rc, addr.EncodeAddress(),
|
||||||
string(addr.ScriptAddress()), cmd.Id())
|
cmd.Id())
|
||||||
}
|
}
|
||||||
|
|
||||||
mreply, _ := json.Marshal(reply)
|
mreply, _ := json.Marshal(reply)
|
||||||
@ -419,67 +419,66 @@ func handleRescan(s *rpcServer, cmd btcjson.Cmd,
|
|||||||
for i := range blkshalist {
|
for i := range blkshalist {
|
||||||
blk, err := s.server.db.FetchBlockBySha(&blkshalist[i])
|
blk, err := s.server.db.FetchBlockBySha(&blkshalist[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rpcsLog.Errorf("Error looking up block sha: %v", err)
|
rpcsLog.Errorf("Error looking up block sha: %v",
|
||||||
|
err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
txs := blk.Transactions()
|
for _, tx := range blk.Transactions() {
|
||||||
for _, tx := range txs {
|
|
||||||
var txReply *btcdb.TxListReply
|
var txReply *btcdb.TxListReply
|
||||||
for txOutIdx, txout := range tx.MsgTx().TxOut {
|
for txOutIdx, txout := range tx.MsgTx().TxOut {
|
||||||
st, txaddrhash, err := btcscript.ScriptToAddrHash(txout.PkScript)
|
_, addrs, _, err := btcscript.ExtractPkScriptAddrs(
|
||||||
if st != btcscript.ScriptAddr || err != nil {
|
txout.PkScript, s.server.btcnet)
|
||||||
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
txaddr, err := btcutil.NewAddressPubKeyHash(txaddrhash, s.server.btcnet)
|
|
||||||
if err != nil {
|
|
||||||
rpcsLog.Errorf("Error creating address: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := rescanCmd.Addresses[txaddr.EncodeAddress()]; ok {
|
for i, addr := range addrs {
|
||||||
// TODO(jrick): This lookup is expensive and can be avoided
|
encodedAddr := addr.EncodeAddress()
|
||||||
// if the wallet is sent the previous outpoints for all inputs
|
if _, ok := rescanCmd.Addresses[encodedAddr]; ok {
|
||||||
// of the tx, so any can removed from the utxo set (since
|
// TODO(jrick): This lookup is expensive and can be avoided
|
||||||
// they are, as of this tx, now spent).
|
// if the wallet is sent the previous outpoints for all inputs
|
||||||
if txReply == nil {
|
// of the tx, so any can removed from the utxo set (since
|
||||||
txReplyList, err := s.server.db.FetchTxBySha(tx.Sha())
|
// they are, as of this tx, now spent).
|
||||||
if err != nil {
|
if txReply == nil {
|
||||||
rpcsLog.Errorf("Tx Sha %v not found by db.", tx.Sha())
|
txReplyList, err := s.server.db.FetchTxBySha(tx.Sha())
|
||||||
return err
|
if err != nil {
|
||||||
}
|
rpcsLog.Errorf("Tx Sha %v not found by db.", tx.Sha())
|
||||||
for i := range txReplyList {
|
return err
|
||||||
if txReplyList[i].Height == blk.Height() {
|
}
|
||||||
txReply = txReplyList[i]
|
for i := range txReplyList {
|
||||||
break
|
if txReplyList[i].Height == blk.Height() {
|
||||||
|
txReply = txReplyList[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
reply.Result = struct {
|
reply.Result = struct {
|
||||||
Receiver string `json:"receiver"`
|
Receiver string `json:"receiver"`
|
||||||
Height int64 `json:"height"`
|
Height int64 `json:"height"`
|
||||||
BlockHash string `json:"blockhash"`
|
BlockHash string `json:"blockhash"`
|
||||||
BlockIndex int `json:"blockindex"`
|
BlockIndex int `json:"blockindex"`
|
||||||
BlockTime int64 `json:"blocktime"`
|
BlockTime int64 `json:"blocktime"`
|
||||||
TxID string `json:"txid"`
|
TxID string `json:"txid"`
|
||||||
TxOutIndex uint32 `json:"txoutindex"`
|
TxOutIndex uint32 `json:"txoutindex"`
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount"`
|
||||||
PkScript string `json:"pkscript"`
|
PkScript string `json:"pkscript"`
|
||||||
Spent bool `json:"spent"`
|
Spent bool `json:"spent"`
|
||||||
}{
|
}{
|
||||||
Receiver: txaddr.EncodeAddress(),
|
Receiver: encodedAddr,
|
||||||
Height: blk.Height(),
|
Height: blk.Height(),
|
||||||
BlockHash: blkshalist[i].String(),
|
BlockHash: blkshalist[i].String(),
|
||||||
BlockIndex: tx.Index(),
|
BlockIndex: tx.Index(),
|
||||||
BlockTime: blk.MsgBlock().Header.Timestamp.Unix(),
|
BlockTime: blk.MsgBlock().Header.Timestamp.Unix(),
|
||||||
TxID: tx.Sha().String(),
|
TxID: tx.Sha().String(),
|
||||||
TxOutIndex: uint32(txOutIdx),
|
TxOutIndex: uint32(txOutIdx),
|
||||||
Amount: txout.Value,
|
Amount: txout.Value,
|
||||||
PkScript: btcutil.Base58Encode(txout.PkScript),
|
PkScript: btcutil.Base58Encode(txout.PkScript),
|
||||||
Spent: txReply.TxSpent[txOutIdx],
|
Spent: txReply.TxSpent[txOutIdx],
|
||||||
|
}
|
||||||
|
mreply, _ := json.Marshal(reply)
|
||||||
|
walletNotification <- mreply
|
||||||
}
|
}
|
||||||
mreply, _ := json.Marshal(reply)
|
|
||||||
walletNotification <- mreply
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -782,66 +781,69 @@ func (s *rpcServer) newBlockNotifyCheckTxIn(tx *btcutil.Tx) {
|
|||||||
// additional block information is passed with the notifications.
|
// additional block information is passed with the notifications.
|
||||||
func (s *rpcServer) NotifyForTxOuts(tx *btcutil.Tx, block *btcutil.Block) {
|
func (s *rpcServer) NotifyForTxOuts(tx *btcutil.Tx, block *btcutil.Block) {
|
||||||
for i, txout := range tx.MsgTx().TxOut {
|
for i, txout := range tx.MsgTx().TxOut {
|
||||||
stype, txaddrhash, err := btcscript.ScriptToAddrHash(txout.PkScript)
|
_, addrs, _, err := btcscript.ExtractPkScriptAddrs(
|
||||||
if stype != btcscript.ScriptAddr || err != nil {
|
txout.PkScript, s.server.btcnet)
|
||||||
// Only support pay-to-pubkey-hash right now.
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if idlist, ok := s.ws.txNotifications[string(txaddrhash)]; ok {
|
|
||||||
for e := idlist.Front(); e != nil; e = e.Next() {
|
|
||||||
ctx := e.Value.(*notificationCtx)
|
|
||||||
|
|
||||||
txaddr, err := btcutil.NewAddressPubKeyHash(txaddrhash, s.server.btcnet)
|
for _, addr := range addrs {
|
||||||
if err != nil {
|
// Only support pay-to-pubkey-hash right now.
|
||||||
rpcsLog.Debugf("Error creating address; dropping Tx notification.")
|
if _, ok := addr.(*btcutil.AddressPubKeyHash); !ok {
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jrick): shove this in btcws
|
encodedAddr := addr.EncodeAddress()
|
||||||
result := struct {
|
if idlist, ok := s.ws.txNotifications[encodedAddr]; ok {
|
||||||
Receiver string `json:"receiver"`
|
for e := idlist.Front(); e != nil; e = e.Next() {
|
||||||
Height int64 `json:"height"`
|
ctx := e.Value.(*notificationCtx)
|
||||||
BlockHash string `json:"blockhash"`
|
|
||||||
BlockIndex int `json:"blockindex"`
|
|
||||||
BlockTime int64 `json:"blocktime"`
|
|
||||||
TxID string `json:"txid"`
|
|
||||||
TxOutIndex uint32 `json:"txoutindex"`
|
|
||||||
Amount int64 `json:"amount"`
|
|
||||||
PkScript string `json:"pkscript"`
|
|
||||||
}{
|
|
||||||
Receiver: txaddr.EncodeAddress(),
|
|
||||||
TxID: tx.Sha().String(),
|
|
||||||
TxOutIndex: uint32(i),
|
|
||||||
Amount: txout.Value,
|
|
||||||
PkScript: btcutil.Base58Encode(txout.PkScript),
|
|
||||||
}
|
|
||||||
|
|
||||||
if block != nil {
|
// TODO(jrick): shove this in btcws
|
||||||
blkhash, err := block.Sha()
|
result := struct {
|
||||||
if err != nil {
|
Receiver string `json:"receiver"`
|
||||||
rpcsLog.Error("Error getting block sha; dropping Tx notification.")
|
Height int64 `json:"height"`
|
||||||
break
|
BlockHash string `json:"blockhash"`
|
||||||
|
BlockIndex int `json:"blockindex"`
|
||||||
|
BlockTime int64 `json:"blocktime"`
|
||||||
|
TxID string `json:"txid"`
|
||||||
|
TxOutIndex uint32 `json:"txoutindex"`
|
||||||
|
Amount int64 `json:"amount"`
|
||||||
|
PkScript string `json:"pkscript"`
|
||||||
|
}{
|
||||||
|
Receiver: encodedAddr,
|
||||||
|
TxID: tx.Sha().String(),
|
||||||
|
TxOutIndex: uint32(i),
|
||||||
|
Amount: txout.Value,
|
||||||
|
PkScript: btcutil.Base58Encode(txout.PkScript),
|
||||||
}
|
}
|
||||||
result.Height = block.Height()
|
|
||||||
result.BlockHash = blkhash.String()
|
|
||||||
result.BlockIndex = tx.Index()
|
|
||||||
result.BlockTime = block.MsgBlock().Header.Timestamp.Unix()
|
|
||||||
} else {
|
|
||||||
result.Height = -1
|
|
||||||
result.BlockIndex = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
reply := &btcjson.Reply{
|
if block != nil {
|
||||||
Result: result,
|
blkhash, err := block.Sha()
|
||||||
Error: nil,
|
if err != nil {
|
||||||
Id: &ctx.id,
|
rpcsLog.Error("Error getting block sha; dropping Tx notification.")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
result.Height = block.Height()
|
||||||
|
result.BlockHash = blkhash.String()
|
||||||
|
result.BlockIndex = tx.Index()
|
||||||
|
result.BlockTime = block.MsgBlock().Header.Timestamp.Unix()
|
||||||
|
} else {
|
||||||
|
result.Height = -1
|
||||||
|
result.BlockIndex = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
reply := &btcjson.Reply{
|
||||||
|
Result: result,
|
||||||
|
Error: nil,
|
||||||
|
Id: &ctx.id,
|
||||||
|
}
|
||||||
|
mreply, err := json.Marshal(reply)
|
||||||
|
if err != nil {
|
||||||
|
rpcsLog.Errorf("Unable to marshal tx notification: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ctx.connection <- mreply
|
||||||
}
|
}
|
||||||
mreply, err := json.Marshal(reply)
|
|
||||||
if err != nil {
|
|
||||||
rpcsLog.Errorf("Unable to marshal tx notification: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ctx.connection <- mreply
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user