Fix build for new btcws notifications.

This commit is contained in:
Josh Rickmar 2013-12-13 11:00:31 -05:00
parent d4e756bc23
commit 75d3a77106
3 changed files with 94 additions and 95 deletions

View file

@ -93,7 +93,11 @@ func (a *Account) Lock() error {
a.mtx.Lock()
defer a.mtx.Unlock()
return a.Wallet.Lock()
err := a.Wallet.Lock()
if err == nil {
NotifyWalletLockStateChange(a.Name(), true)
}
return err
}
// Unlock unlocks the underlying wallet for an account.
@ -101,6 +105,10 @@ func (a *Account) Unlock(passphrase []byte, timeout int64) error {
a.mtx.Lock()
defer a.mtx.Unlock()
err := a.Wallet.Unlock(passphrase)
if err == nil {
NotifyWalletLockStateChange(a.Name(), false)
}
return a.Wallet.Unlock(passphrase)
}

View file

@ -1055,7 +1055,6 @@ func WalletPassphrase(frontend chan []byte, icmd btcjson.Cmd) {
case nil:
ReplySuccess(frontend, cmd.Id(), nil)
NotifyWalletLockStateChange("", false)
go func(timeout int64) {
time.Sleep(time.Second * time.Duration(timeout))
_ = a.Lock()
@ -1083,46 +1082,25 @@ type AccountNtfn struct {
// NotifyWalletLockStateChange sends a notification to all frontends
// that the wallet has just been locked or unlocked.
func NotifyWalletLockStateChange(account string, locked bool) {
var id interface{} = "btcwallet:newwalletlockstate"
m := btcjson.Reply{
Result: &AccountNtfn{
Account: account,
Notification: locked,
},
Id: &id,
}
msg, _ := json.Marshal(&m)
frontendNotificationMaster <- msg
ntfn := btcws.NewWalletLockStateNtfn(account, locked)
mntfn, _ := ntfn.MarshalJSON()
frontendNotificationMaster <- mntfn
}
// NotifyWalletBalance sends a confirmed account balance notification
// to a frontend.
func NotifyWalletBalance(frontend chan []byte, account string, balance float64) {
var id interface{} = "btcwallet:accountbalance"
m := btcjson.Reply{
Result: &AccountNtfn{
Account: account,
Notification: balance,
},
Id: &id,
}
msg, _ := json.Marshal(&m)
frontend <- msg
ntfn := btcws.NewAccountBalanceNtfn(account, balance, true)
mntfn, _ := ntfn.MarshalJSON()
frontend <- mntfn
}
// NotifyWalletBalanceUnconfirmed sends a confirmed account balance
// notification to a frontend.
func NotifyWalletBalanceUnconfirmed(frontend chan []byte, account string, balance float64) {
var id interface{} = "btcwallet:accountbalanceunconfirmed"
m := btcjson.Reply{
Result: &AccountNtfn{
Account: account,
Notification: balance,
},
Id: &id,
}
msg, _ := json.Marshal(&m)
frontend <- msg
ntfn := btcws.NewAccountBalanceNtfn(account, balance, false)
mntfn, _ := ntfn.MarshalJSON()
frontend <- mntfn
}
// NotifyNewTxDetails sends details of a new transaction to a frontend.

View file

@ -345,7 +345,7 @@ func frontendListenerDuplicator() {
NotifyBtcdConnected(frontendNotificationMaster,
btcdConnected.b)
if bs, err := GetCurBlock(); err == nil {
NotifyNewBlockChainHeight(c, bs.Height)
NotifyNewBlockChainHeight(c, bs)
NotifyBalances(c)
}
@ -381,13 +381,10 @@ func frontendListenerDuplicator() {
// NotifyBtcdConnected notifies all frontends of a new btcd connection.
func NotifyBtcdConnected(reply chan []byte, conn bool) {
btcdConnected.b = conn
var idStr interface{} = "btcwallet:btcdconnected"
r := btcjson.Reply{
Result: conn,
Id: &idStr,
}
ntfn, _ := json.Marshal(r)
frontendNotificationMaster <- ntfn
ntfn := btcws.NewBtcdConnectedNtfn(conn)
mntfn, _ := ntfn.MarshalJSON()
frontendNotificationMaster <- mntfn
}
// frontendSendRecv is the handler function for websocket connections from
@ -481,12 +478,12 @@ func BtcdHandler(ws *websocket.Conn, done chan struct{}) {
}()
}
type notificationHandler func(btcws.Notification)
type notificationHandler func(btcjson.Cmd, []byte)
var notificationHandlers = map[string]notificationHandler{
btcws.BlockConnectedNtfnId: NtfnBlockConnected,
btcws.BlockDisconnectedNtfnId: NtfnBlockDisconnected,
btcws.TxMinedNtfnId: NtfnTxMined,
btcws.BlockConnectedNtfnMethod: NtfnBlockConnected,
btcws.BlockDisconnectedNtfnMethod: NtfnBlockDisconnected,
btcws.TxMinedNtfnMethod: NtfnTxMined,
}
// ProcessBtcdNotificationReply unmarshalls the JSON notification or
@ -495,29 +492,63 @@ var notificationHandlers = map[string]notificationHandler{
// notifications are processed by btcwallet, and frontend notifications
// are sent to every connected frontend.
func ProcessBtcdNotificationReply(b []byte) {
// Check if the json id field was set by btcwallet.
var routeID uint64
var origID string
// Idea: instead of reading btcd messages from just one websocket
// connection, maybe use two so the same connection isn't used
// for both notifications and responses? Should make handling
// must faster as unnecessary unmarshal attempts could be avoided.
var r btcjson.Reply
if err := json.Unmarshal(b, &r); err != nil {
log.Errorf("Unable to unmarshal btcd message: %v", err)
// Check for notifications first.
if req, err := btcjson.ParseMarshaledCmd(b); err == nil {
// btcd should not be sending Requests except for
// notifications. Check for a nil id.
if req.Id() != nil {
// Invalid response
log.Warnf("btcd sent a non-notification JSON-RPC Request (ID: %v)",
req.Id())
return
}
// Message is a btcd notification. Check the method and dispatch
// correct handler, or if no handler, pass up to each wallet.
if ntfnHandler, ok := notificationHandlers[req.Method()]; ok {
ntfnHandler(req, b)
} else {
// No handler; send to all wallets.
frontendNotificationMaster <- b
}
return
}
// b is not a Request notification, so it must be a Response.
// Attempt to parse it as one and handle.
var r btcjson.Reply
if err := json.Unmarshal(b, &r); err != nil {
log.Warn("Unable to process btcd message as notification or response")
return
}
// Check for a valid ID.
//
// TODO(jrick): Remove this terrible ID overloading. Each
// passed-through request should be given a new unique ID number
// (reading from the NewJSONID channel) and a reply route with the
// frontend's incoming ID should be set.
if r.Id == nil {
// btcd should only ever be sending JSON messages with a string in
// the id field. Log the error and drop the message.
log.Error("Unable to process btcd notification or reply.")
// Responses with no IDs cannot be handled.
log.Warn("Unable to process btcd response without ID")
return
}
idStr, ok := (*r.Id).(string)
if !ok {
// btcd should only ever be sending JSON messages with a string in
// the id field. Log the error and drop the message.
// btcd's responses to btcwallet should (currently, see TODO above)
// only ever be sending string IDs. If ID is not a string, log the
// error and drop the message.
log.Error("Incorrect btcd notification id type.")
return
}
var routeID uint64
var origID string
n, _ := fmt.Sscanf(idStr, "btcwallet(%d)-%s", &routeID, &origID)
if n == 1 {
// Request originated from btcwallet. Run and remove correct
@ -565,34 +596,16 @@ func ProcessBtcdNotificationReply(b []byte) {
return
}
c <- b
} else {
// Message is a btcd notification. Check the id and dispatch
// correct handler, or if no handler, pass up to each wallet.
if ntfnHandler, ok := notificationHandlers[idStr]; ok {
n, err := btcws.ParseMarshaledNtfn(idStr, b)
if err != nil {
log.Errorf("Error unmarshaling expected "+
"notification: %v", err)
return
}
ntfnHandler(n)
return
}
frontendNotificationMaster <- b
}
}
// NotifyNewBlockChainHeight notifies all frontends of a new
// blockchain height.
func NotifyNewBlockChainHeight(reply chan []byte, height int32) {
var id interface{} = "btcwallet:newblockchainheight"
msgRaw := &btcjson.Reply{
Result: height,
Id: &id,
}
msg, _ := json.Marshal(msgRaw)
reply <- msg
// blockchain height. This sends the same notification as
// btcd, so this can probably be removed.
func NotifyNewBlockChainHeight(reply chan []byte, bs wallet.BlockStamp) {
ntfn := btcws.NewBlockConnectedNtfn(bs.Hash.String(), bs.Height)
mntfn, _ := ntfn.MarshalJSON()
reply <- mntfn
}
// NtfnBlockConnected handles btcd notifications resulting from newly
@ -602,15 +615,15 @@ func NotifyNewBlockChainHeight(reply chan []byte, height int32) {
// to mark wallet files with a possibly-better earliest block height,
// and will greatly reduce rescan times for wallets created with an
// out of sync btcd.
func NtfnBlockConnected(n btcws.Notification) {
func NtfnBlockConnected(n btcjson.Cmd, marshaled []byte) {
bcn, ok := n.(*btcws.BlockConnectedNtfn)
if !ok {
log.Errorf("%v handler: unexpected type", n.Id())
log.Errorf("%v handler: unexpected type", n.Method())
return
}
hash, err := btcwire.NewShaHashFromStr(bcn.Hash)
if err != nil {
log.Errorf("%v handler: invalid hash string", n.Id())
log.Errorf("%v handler: invalid hash string", n.Method())
return
}
@ -630,22 +643,22 @@ func NtfnBlockConnected(n btcws.Notification) {
accountstore.BlockNotify(bs)
// Notify frontends of new blockchain height.
NotifyNewBlockChainHeight(frontendNotificationMaster, bcn.Height)
// Pass notification to frontends too.
frontendNotificationMaster <- marshaled
}
// NtfnBlockDisconnected handles btcd notifications resulting from
// blocks disconnected from the main chain in the event of a chain
// switch and notifies frontends of the new blockchain height.
func NtfnBlockDisconnected(n btcws.Notification) {
func NtfnBlockDisconnected(n btcjson.Cmd, marshaled []byte) {
bdn, ok := n.(*btcws.BlockDisconnectedNtfn)
if !ok {
log.Errorf("%v handler: unexpected type", n.Id())
log.Errorf("%v handler: unexpected type", n.Method())
return
}
hash, err := btcwire.NewShaHashFromStr(bdn.Hash)
if err != nil {
log.Errorf("%v handler: invalid hash string", n.Id())
log.Errorf("%v handler: invalid hash string", n.Method())
return
}
@ -654,34 +667,34 @@ func NtfnBlockDisconnected(n btcws.Notification) {
accountstore.Rollback(bdn.Height, hash)
}()
// Notify frontends of new blockchain height.
NotifyNewBlockChainHeight(frontendNotificationMaster, bdn.Height)
// Pass notification to frontends too.
frontendNotificationMaster <- marshaled
}
// NtfnTxMined handles btcd notifications resulting from newly
// mined transactions that originated from this wallet.
func NtfnTxMined(n btcws.Notification) {
func NtfnTxMined(n btcjson.Cmd, marshaled []byte) {
tmn, ok := n.(*btcws.TxMinedNtfn)
if !ok {
log.Errorf("%v handler: unexpected type", n.Id())
log.Errorf("%v handler: unexpected type", n.Method())
return
}
txid, err := btcwire.NewShaHashFromStr(tmn.TxID)
if err != nil {
log.Errorf("%v handler: invalid hash string", n.Id())
log.Errorf("%v handler: invalid hash string", n.Method())
return
}
blockhash, err := btcwire.NewShaHashFromStr(tmn.BlockHash)
if err != nil {
log.Errorf("%v handler: invalid block hash string", n.Id())
log.Errorf("%v handler: invalid block hash string", n.Method())
return
}
err = accountstore.RecordMinedTx(txid, blockhash,
tmn.BlockHeight, tmn.Index, tmn.BlockTime)
if err != nil {
log.Errorf("%v handler: %v", n.Id(), err)
log.Errorf("%v handler: %v", n.Method(), err)
return
}
@ -900,7 +913,7 @@ func BtcdHandshake(ws *websocket.Conn) error {
if err != nil {
return fmt.Errorf("cannot get best block: %v", err)
}
NotifyNewBlockChainHeight(frontendNotificationMaster, bs.Height)
NotifyNewBlockChainHeight(frontendNotificationMaster, bs)
NotifyBalances(frontendNotificationMaster)
// Get default account. Only the default account is used to