Add support for running wallet on testnet3.
Websocket connections to btcd will be closed if btcd and btcwallet are running on different networks.
This commit is contained in:
parent
1d6741eb05
commit
3c4ff4b0f4
5 changed files with 98 additions and 17 deletions
40
cmdmgr.go
40
cmdmgr.go
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcwallet/wallet"
|
||||
"github.com/conformal/btcwire"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
@ -568,22 +569,37 @@ func SendMany(reply chan []byte, msg *btcjson.Message) {
|
|||
// All three parameters are required, and must be of type string. If
|
||||
// the wallet specified by account already exists, an invalid account
|
||||
// name error is returned to the client.
|
||||
//
|
||||
// Wallets will be created on MainNet, or TestNet3 if btcwallet is run with
|
||||
// the --testnet option.
|
||||
func CreateEncryptedWallet(reply chan []byte, msg *btcjson.Message) {
|
||||
params, ok := msg.Params.([]interface{})
|
||||
e := &InvalidParams
|
||||
if !ok {
|
||||
log.Error("CreateEncryptedWallet: Cannot parse parameters.")
|
||||
ReplyError(reply, msg.Id, e)
|
||||
return
|
||||
}
|
||||
var wname string
|
||||
if len(params) != 3 {
|
||||
ReplyError(reply, msg.Id, &InvalidParams)
|
||||
e.Message = "Incorrect number of parameters"
|
||||
ReplyError(reply, msg.Id, e)
|
||||
return
|
||||
}
|
||||
wname, ok1 := params[0].(string)
|
||||
desc, ok2 := params[1].(string)
|
||||
pass, ok3 := params[2].(string)
|
||||
if !ok1 || !ok2 || !ok3 {
|
||||
ReplyError(reply, msg.Id, &InvalidParams)
|
||||
wname, ok := params[0].(string)
|
||||
if !ok {
|
||||
e.Message = "Account is not a string"
|
||||
ReplyError(reply, msg.Id, e)
|
||||
return
|
||||
}
|
||||
desc, ok := params[1].(string)
|
||||
if !ok {
|
||||
e.Message = "Description is not a string"
|
||||
ReplyError(reply, msg.Id, e)
|
||||
return
|
||||
}
|
||||
pass, ok := params[2].(string)
|
||||
if !ok {
|
||||
e.Message = "Passphrase is not a string"
|
||||
ReplyError(reply, msg.Id, e)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -597,7 +613,13 @@ func CreateEncryptedWallet(reply chan []byte, msg *btcjson.Message) {
|
|||
}
|
||||
wallets.RUnlock()
|
||||
|
||||
w, err := wallet.NewWallet(wname, desc, []byte(pass))
|
||||
var net btcwire.BitcoinNet
|
||||
if cfg.TestNet3 {
|
||||
net = btcwire.TestNet3
|
||||
} else {
|
||||
net = btcwire.MainNet
|
||||
}
|
||||
w, err := wallet.NewWallet(wname, desc, []byte(pass), net)
|
||||
if err != nil {
|
||||
log.Error("Error creating wallet: " + err.Error())
|
||||
ReplyError(reply, msg.Id, &InternalError)
|
||||
|
|
|
@ -45,6 +45,7 @@ type config struct {
|
|||
DataDir string `short:"D" long:"datadir" description:"Directory to store wallets and transactions"`
|
||||
Username string `short:"u" long:"username" description:"Username for btcd authorization"`
|
||||
Password string `short:"P" long:"password" description:"Password for btcd authorization"`
|
||||
TestNet3 bool `long:"testnet" description:"Use the test network"`
|
||||
}
|
||||
|
||||
// btcwalletHomeDir returns an OS appropriate home directory for btcwallet.
|
||||
|
|
67
sockets.go
67
sockets.go
|
@ -61,7 +61,8 @@ var (
|
|||
// replyHandlers maps between a sequence number (passed as part of
|
||||
// the JSON Id field) and a function to handle a reply or notification
|
||||
// from btcd. As requests are received, this map is checked for a
|
||||
// handler function to route the reply to.
|
||||
// handler function to route the reply to. If the function returns
|
||||
// true, the handler is removed from the map.
|
||||
replyHandlers = struct {
|
||||
sync.Mutex
|
||||
m map[uint64]func(interface{}, *btcjson.Error) bool
|
||||
|
@ -178,8 +179,9 @@ func frontendReqsNotifications(ws *websocket.Conn) {
|
|||
// websocket and sends messages that btcwallet does not understand to
|
||||
// btcd. Unlike FrontendHandler, exactly one BtcdHandler goroutine runs.
|
||||
func BtcdHandler(ws *websocket.Conn) {
|
||||
// Notification channel to return from listener goroutine when
|
||||
// btcd disconnects.
|
||||
disconnected := make(chan int)
|
||||
|
||||
defer func() {
|
||||
close(disconnected)
|
||||
}()
|
||||
|
@ -214,6 +216,7 @@ func BtcdHandler(ws *websocket.Conn) {
|
|||
case r := <-btcdMsgs:
|
||||
if err := websocket.Message.Send(ws, r); err != nil {
|
||||
// btcd disconnected.
|
||||
log.Error("Unable to send message to btcd: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -446,13 +449,67 @@ func BtcdConnect(reply chan error) {
|
|||
close(handlerClosed)
|
||||
}()
|
||||
|
||||
BtcdHandshake(btcdws)
|
||||
|
||||
<-handlerClosed
|
||||
reply <- ErrConnLost
|
||||
}
|
||||
|
||||
// BtcdHandshake first checks that the websocket connection between
|
||||
// btcwallet and btcd is valid, that is, that there are no mismatching
|
||||
// settings between the two processes (such as running on different
|
||||
// Bitcoin networks). If the sanity checks pass, all wallets are set to
|
||||
// be tracked against chain notifications from this btcd connection.
|
||||
func BtcdHandshake(ws *websocket.Conn) {
|
||||
seq.Lock()
|
||||
n := seq.n
|
||||
seq.n++
|
||||
seq.Unlock()
|
||||
msg := btcjson.Message{
|
||||
Method: "getcurrentnet",
|
||||
Id: fmt.Sprintf("btcwallet(%v)", n),
|
||||
}
|
||||
m, _ := json.Marshal(&msg)
|
||||
|
||||
correctNetwork := make(chan bool)
|
||||
|
||||
replyHandlers.Lock()
|
||||
replyHandlers.m[n] = func(result interface{}, err *btcjson.Error) bool {
|
||||
fmt.Println("got reply")
|
||||
fnet, ok := result.(float64)
|
||||
if !ok {
|
||||
log.Error("btcd handshake: result is not a number")
|
||||
ws.Close()
|
||||
correctNetwork <- false
|
||||
return true
|
||||
}
|
||||
|
||||
var walletNetwork btcwire.BitcoinNet
|
||||
if cfg.TestNet3 {
|
||||
walletNetwork = btcwire.TestNet3
|
||||
} else {
|
||||
walletNetwork = btcwire.MainNet
|
||||
}
|
||||
|
||||
correctNetwork <- btcwire.BitcoinNet(fnet) == walletNetwork
|
||||
|
||||
// No additional replies expected, remove handler.
|
||||
return true
|
||||
}
|
||||
replyHandlers.Unlock()
|
||||
|
||||
btcdMsgs <- m
|
||||
|
||||
if !<-correctNetwork {
|
||||
log.Error("btcd and btcwallet running on different Bitcoin networks")
|
||||
ws.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// Begin tracking wallets against this btcd instance.
|
||||
wallets.RLock()
|
||||
for _, w := range wallets.m {
|
||||
w.Track()
|
||||
}
|
||||
wallets.RUnlock()
|
||||
|
||||
<-handlerClosed
|
||||
reply <- ErrConnLost
|
||||
}
|
||||
|
|
|
@ -353,7 +353,7 @@ type Wallet struct {
|
|||
// desc's binary representation must not exceed 32 and 256 bytes,
|
||||
// respectively. All address private keys are encrypted with passphrase.
|
||||
// The wallet is returned unlocked.
|
||||
func NewWallet(name, desc string, passphrase []byte) (*Wallet, error) {
|
||||
func NewWallet(name, desc string, passphrase []byte, net btcwire.BitcoinNet) (*Wallet, error) {
|
||||
if binary.Size(name) > 32 {
|
||||
return nil, errors.New("name exceeds 32 byte maximum size")
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ func NewWallet(name, desc string, passphrase []byte) (*Wallet, error) {
|
|||
// compat with armory.
|
||||
w := &Wallet{
|
||||
version: 0, // TODO(jrick): implement versioning
|
||||
net: btcwire.MainNet,
|
||||
net: net,
|
||||
flags: walletFlags{
|
||||
useEncryption: true,
|
||||
watchingOnly: false,
|
||||
|
|
|
@ -18,6 +18,7 @@ package wallet
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"github.com/conformal/btcwire"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"os"
|
||||
"reflect"
|
||||
|
@ -78,7 +79,7 @@ func TestBtcAddressSerializer(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWalletCreationSerialization(t *testing.T) {
|
||||
w1, err := NewWallet("banana wallet", "A wallet for testing.", []byte("banana"))
|
||||
w1, err := NewWallet("banana wallet", "A wallet for testing.", []byte("banana"), btcwire.MainNet)
|
||||
if err != nil {
|
||||
t.Error("Error creating new wallet: " + err.Error())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue