Begin using btcws.

This change begins using the btcws package for marshaling custom
commands used for websocket connections to btcd.
This commit is contained in:
Josh Rickmar 2013-11-06 11:23:30 -05:00
parent f3408bad91
commit e65206f752
4 changed files with 87 additions and 50 deletions

94
cmd.go
View file

@ -18,7 +18,6 @@ package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/conformal/btcjson"
@ -26,6 +25,7 @@ import (
"github.com/conformal/btcwallet/tx"
"github.com/conformal/btcwallet/wallet"
"github.com/conformal/btcwire"
"github.com/conformal/btcws"
"os"
"path/filepath"
"sync"
@ -244,12 +244,13 @@ func GetCurBlock() (bs wallet.BlockStamp, err error) {
}
n := <-NewJSONID
msg := btcjson.Message{
Jsonrpc: "1.0",
Id: fmt.Sprintf("btcwallet(%v)", n),
Method: "getbestblock",
cmd := btcws.NewGetBestBlockCmd(fmt.Sprintf("btcwallet(%v)", n))
mcmd, err := cmd.MarshalJSON()
if err != nil {
return wallet.BlockStamp{
Height: int32(btcutil.BlockHeightUnknown),
}, errors.New("cannot ask for best block")
}
m, _ := json.Marshal(msg)
c := make(chan *struct {
hash *btcwire.ShaHash
@ -294,7 +295,7 @@ func GetCurBlock() (bs wallet.BlockStamp, err error) {
replyHandlers.Unlock()
// send message
btcdMsgs <- m
btcdMsgs <- mcmd
// Block until reply is ready.
if reply := <-c; reply != nil {
@ -402,17 +403,17 @@ func (w *BtcWallet) RescanToBestBlock() {
}
n := <-NewJSONID
params := []interface{}{
beginBlock,
w.ActivePaymentAddresses(),
cmd, err := btcws.NewRescanCmd(fmt.Sprintf("btcwallet(%v)", n),
beginBlock, w.ActivePaymentAddresses())
if err != nil {
log.Errorf("cannot create rescan request: %v", err)
return
}
m := &btcjson.Message{
Jsonrpc: "1.0",
Id: fmt.Sprintf("btcwallet(%v)", n),
Method: "rescan",
Params: params,
mcmd, err := cmd.MarshalJSON()
if err != nil {
log.Errorf("cannot create rescan request: %v", err)
return
}
msg, _ := json.Marshal(m)
replyHandlers.Lock()
replyHandlers.m[n] = func(result interface{}, e *btcjson.Error) bool {
@ -443,21 +444,36 @@ func (w *BtcWallet) RescanToBestBlock() {
}
replyHandlers.Unlock()
btcdMsgs <- msg
btcdMsgs <- mcmd
}
// ActivePaymentAddresses returns the second parameter for all rescan
// commands. The returned slice maps between payment address strings and
// the block height to begin rescanning for transactions to that address.
func (w *BtcWallet) ActivePaymentAddresses() []string {
// SortedActivePaymentAddresses returns a slice of all active payment
// addresses in an account.
func (w *BtcWallet) SortedActivePaymentAddresses() []string {
w.mtx.RLock()
defer w.mtx.RUnlock()
infos := w.GetSortedActiveAddresses()
addrs := make([]string, len(infos))
for i, addr := range infos {
addrs[i] = addr.Address
}
return addrs
}
// ActivePaymentAddresses returns a set of all active pubkey hashes
// in an account.
func (w *BtcWallet) ActivePaymentAddresses() map[string]struct{} {
w.mtx.RLock()
defer w.mtx.RUnlock()
infos := w.GetActiveAddresses()
addrs := make([]string, len(infos))
addrs := make(map[string]struct{}, len(infos))
for i := range infos {
addrs[i] = infos[i].Address
for _, info := range infos {
addrs[info.Address] = struct{}{}
}
return addrs
@ -472,15 +488,14 @@ func (w *BtcWallet) ReqNewTxsForAddress(addr string) {
n := w.NewBlockTxSeqN
w.mtx.RUnlock()
m := &btcjson.Message{
Jsonrpc: "1.0",
Id: fmt.Sprintf("btcwallet(%d)", n),
Method: "notifynewtxs",
Params: []interface{}{addr},
cmd := btcws.NewNotifyNewTXsCmd(fmt.Sprintf("btcwallet(%d)", n),
[]string{addr})
mcmd, err := cmd.MarshalJSON()
if err != nil {
log.Errorf("cannot request transaction notifications: %v", err)
}
msg, _ := json.Marshal(m)
btcdMsgs <- msg
btcdMsgs <- mcmd
}
// ReqSpentUtxoNtfn sends a message to btcd to request updates for when
@ -493,18 +508,15 @@ func (w *BtcWallet) ReqSpentUtxoNtfn(u *tx.Utxo) {
n := w.SpentOutpointSeqN
w.mtx.RUnlock()
m := &btcjson.Message{
Jsonrpc: "1.0",
Id: fmt.Sprintf("btcwallet(%d)", n),
Method: "notifyspent",
Params: []interface{}{
u.Out.Hash.String(),
u.Out.Index,
},
cmd := btcws.NewNotifySpentCmd(fmt.Sprintf("btcwallet(%d)", n),
(*btcwire.OutPoint)(&u.Out))
mcmd, err := cmd.MarshalJSON()
if err != nil {
log.Errorf("cannot create spent request: %v", err)
return
}
msg, _ := json.Marshal(m)
btcdMsgs <- msg
btcdMsgs <- mcmd
}
// spentUtxoHandler is the handler function for btcd spent UTXO notifications

View file

@ -139,7 +139,7 @@ func GetAddressesByAccount(reply chan []byte, msg *btcjson.Message) {
var result []string
if w := wallets.m[account]; w != nil {
result = w.ActivePaymentAddresses()
result = w.SortedActivePaymentAddresses()
} else {
ReplyError(reply, msg.Id, &btcjson.ErrWalletInvalidAccountName)
return

View file

@ -25,6 +25,7 @@ import (
"github.com/conformal/btcjson"
"github.com/conformal/btcwallet/wallet"
"github.com/conformal/btcwire"
"github.com/conformal/btcws"
"net"
"net/http"
"sync"
@ -562,11 +563,13 @@ func BtcdConnect(reply chan error) {
// be tracked against chain notifications from this btcd connection.
func BtcdHandshake(ws *websocket.Conn) {
n := <-NewJSONID
msg := btcjson.Message{
Method: "getcurrentnet",
Id: fmt.Sprintf("btcwallet(%v)", n),
cmd := btcws.NewGetCurrentNetCmd(fmt.Sprintf("btcwallet(%v)", n))
mcmd, err := cmd.MarshalJSON()
if err != nil {
log.Errorf("Cannot complete btcd handshake: %v", err)
ws.Close()
return
}
m, _ := json.Marshal(&msg)
correctNetwork := make(chan bool)
@ -594,7 +597,7 @@ func BtcdHandshake(ws *websocket.Conn) {
}
replyHandlers.Unlock()
btcdMsgs <- m
btcdMsgs <- mcmd
if !<-correctNetwork {
log.Error("btcd and btcwallet running on different Bitcoin networks")

View file

@ -775,14 +775,16 @@ func (w *Wallet) addr160ForIdx(idx int64) (addressHashKey, error) {
// a complete wallet.
type AddressInfo struct {
Address string
AddrHash string
FirstBlock int32
Compressed bool
}
// GetActiveAddresses returns all wallet addresses that have been
// GetSortedActiveAddresses returns all wallet addresses that have been
// requested to be generated. These do not include pre-generated
// addresses.
func (w *Wallet) GetActiveAddresses() []*AddressInfo {
// addresses. Use this when ordered addresses are needed. Otherwise,
// GetActiveAddresses is preferred.
func (w *Wallet) GetSortedActiveAddresses() []*AddressInfo {
addrs := make([]*AddressInfo, 0, w.highestUsed+1)
for i := int64(-1); i <= w.highestUsed; i++ {
addr160, err := w.addr160ForIdx(i)
@ -798,6 +800,25 @@ func (w *Wallet) GetActiveAddresses() []*AddressInfo {
return addrs
}
// GetActiveAddresses returns a map between active payment addresses
// and their full info. These do not include pre-generated addresses.
// If addresses must be sorted, use GetSortedActiveAddresses.
func (w *Wallet) GetActiveAddresses() map[string]*AddressInfo {
addrs := make(map[string]*AddressInfo)
for i := int64(-1); i <= w.highestUsed; i++ {
addr160, err := w.addr160ForIdx(i)
if err != nil {
return addrs
}
addr := w.addrMap[addr160]
info, err := addr.info(w.Net())
if err == nil {
addrs[info.Address] = info
}
}
return addrs
}
type walletFlags struct {
useEncryption bool
watchingOnly bool
@ -1181,6 +1202,7 @@ func (a *btcAddress) info(net btcwire.BitcoinNet) (*AddressInfo, error) {
return &AddressInfo{
Address: address,
AddrHash: string(a.pubKeyHash[:]),
FirstBlock: a.firstBlock,
Compressed: a.flags.compressed,
}, nil