mirror of
https://github.com/LBRYFoundation/lbcwallet.git
synced 2025-08-23 17:47:29 +00:00
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"
|
"fmt"
|
||||||
"github.com/conformal/btcjson"
|
"github.com/conformal/btcjson"
|
||||||
"github.com/conformal/btcwallet/wallet"
|
"github.com/conformal/btcwallet/wallet"
|
||||||
|
"github.com/conformal/btcwire"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"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
|
// All three parameters are required, and must be of type string. If
|
||||||
// the wallet specified by account already exists, an invalid account
|
// the wallet specified by account already exists, an invalid account
|
||||||
// name error is returned to the client.
|
// 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) {
|
func CreateEncryptedWallet(reply chan []byte, msg *btcjson.Message) {
|
||||||
params, ok := msg.Params.([]interface{})
|
params, ok := msg.Params.([]interface{})
|
||||||
|
e := &InvalidParams
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("CreateEncryptedWallet: Cannot parse parameters.")
|
ReplyError(reply, msg.Id, e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var wname string
|
|
||||||
if len(params) != 3 {
|
if len(params) != 3 {
|
||||||
ReplyError(reply, msg.Id, &InvalidParams)
|
e.Message = "Incorrect number of parameters"
|
||||||
|
ReplyError(reply, msg.Id, e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wname, ok1 := params[0].(string)
|
wname, ok := params[0].(string)
|
||||||
desc, ok2 := params[1].(string)
|
if !ok {
|
||||||
pass, ok3 := params[2].(string)
|
e.Message = "Account is not a string"
|
||||||
if !ok1 || !ok2 || !ok3 {
|
ReplyError(reply, msg.Id, e)
|
||||||
ReplyError(reply, msg.Id, &InvalidParams)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +613,13 @@ func CreateEncryptedWallet(reply chan []byte, msg *btcjson.Message) {
|
||||||
}
|
}
|
||||||
wallets.RUnlock()
|
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 {
|
if err != nil {
|
||||||
log.Error("Error creating wallet: " + err.Error())
|
log.Error("Error creating wallet: " + err.Error())
|
||||||
ReplyError(reply, msg.Id, &InternalError)
|
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"`
|
DataDir string `short:"D" long:"datadir" description:"Directory to store wallets and transactions"`
|
||||||
Username string `short:"u" long:"username" description:"Username for btcd authorization"`
|
Username string `short:"u" long:"username" description:"Username for btcd authorization"`
|
||||||
Password string `short:"P" long:"password" description:"Password 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.
|
// 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
|
// replyHandlers maps between a sequence number (passed as part of
|
||||||
// the JSON Id field) and a function to handle a reply or notification
|
// 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
|
// 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 {
|
replyHandlers = struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
m map[uint64]func(interface{}, *btcjson.Error) bool
|
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
|
// websocket and sends messages that btcwallet does not understand to
|
||||||
// btcd. Unlike FrontendHandler, exactly one BtcdHandler goroutine runs.
|
// btcd. Unlike FrontendHandler, exactly one BtcdHandler goroutine runs.
|
||||||
func BtcdHandler(ws *websocket.Conn) {
|
func BtcdHandler(ws *websocket.Conn) {
|
||||||
|
// Notification channel to return from listener goroutine when
|
||||||
|
// btcd disconnects.
|
||||||
disconnected := make(chan int)
|
disconnected := make(chan int)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
close(disconnected)
|
close(disconnected)
|
||||||
}()
|
}()
|
||||||
|
@ -214,6 +216,7 @@ func BtcdHandler(ws *websocket.Conn) {
|
||||||
case r := <-btcdMsgs:
|
case r := <-btcdMsgs:
|
||||||
if err := websocket.Message.Send(ws, r); err != nil {
|
if err := websocket.Message.Send(ws, r); err != nil {
|
||||||
// btcd disconnected.
|
// btcd disconnected.
|
||||||
|
log.Error("Unable to send message to btcd: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,13 +449,67 @@ func BtcdConnect(reply chan error) {
|
||||||
close(handlerClosed)
|
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.
|
// Begin tracking wallets against this btcd instance.
|
||||||
wallets.RLock()
|
wallets.RLock()
|
||||||
for _, w := range wallets.m {
|
for _, w := range wallets.m {
|
||||||
w.Track()
|
w.Track()
|
||||||
}
|
}
|
||||||
wallets.RUnlock()
|
wallets.RUnlock()
|
||||||
|
|
||||||
<-handlerClosed
|
|
||||||
reply <- ErrConnLost
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,7 +353,7 @@ type Wallet struct {
|
||||||
// desc's binary representation must not exceed 32 and 256 bytes,
|
// desc's binary representation must not exceed 32 and 256 bytes,
|
||||||
// respectively. All address private keys are encrypted with passphrase.
|
// respectively. All address private keys are encrypted with passphrase.
|
||||||
// The wallet is returned unlocked.
|
// 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 {
|
if binary.Size(name) > 32 {
|
||||||
return nil, errors.New("name exceeds 32 byte maximum size")
|
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.
|
// compat with armory.
|
||||||
w := &Wallet{
|
w := &Wallet{
|
||||||
version: 0, // TODO(jrick): implement versioning
|
version: 0, // TODO(jrick): implement versioning
|
||||||
net: btcwire.MainNet,
|
net: net,
|
||||||
flags: walletFlags{
|
flags: walletFlags{
|
||||||
useEncryption: true,
|
useEncryption: true,
|
||||||
watchingOnly: false,
|
watchingOnly: false,
|
||||||
|
|
|
@ -18,6 +18,7 @@ package wallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"github.com/conformal/btcwire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -78,7 +79,7 @@ func TestBtcAddressSerializer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWalletCreationSerialization(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 {
|
if err != nil {
|
||||||
t.Error("Error creating new wallet: " + err.Error())
|
t.Error("Error creating new wallet: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue