Skip to content

Instantly share code, notes, and snippets.

@tuxcanfly

tuxcanfly/rpc.go Secret

Last active August 29, 2015 14:03
Show Gist options
  • Save tuxcanfly/84a66a35bf4b32904415 to your computer and use it in GitHub Desktop.
Save tuxcanfly/84a66a35bf4b32904415 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"time"
rpc "github.com/conformal/btcrpcclient"
"github.com/conformal/btcutil"
)
const connRetry = 15
type ChainServer struct {
connect string
user string
pass string
certPath string
keyPath string
cert []byte
}
type procArgs struct {
chainSvr ChainServer
dir string
port string
walletPassphrase string
}
var defaultChainServer = ChainServer{
connect: "localhost:18556", // local simnet btcd
user: "rpcuser",
pass: "rpcpass",
}
var console ConsoleWriter
type ConsoleWriter struct{}
func (cons ConsoleWriter) Print(p string) (n int, err error) {
return cons.Write([]byte(p))
}
func (cons ConsoleWriter) Write(p []byte) (n int, err error) {
fmt.Println(string(p))
return len(p), nil
}
func main() {
rpc.SetLogWriter(console, "trace")
// Initialize btcd, btcwallet args
btcdHomeDir := btcutil.AppDataDir("btcd", false)
defaultChainServer.certPath = filepath.Join(btcdHomeDir, "rpc.cert")
defaultChainServer.keyPath = filepath.Join(btcdHomeDir, "rpc.key")
cert, err := ioutil.ReadFile(defaultChainServer.certPath)
if err != nil {
log.Fatalf("Cannot read certificate: %v", err)
}
defaultChainServer.cert = cert
dir, err := ioutil.TempDir("", "actor")
if err != nil {
return
}
p := procArgs{
chainSvr: defaultChainServer,
dir: dir,
port: "18557",
walletPassphrase: "walletpass",
}
args := []string{
"--simnet",
"--datadir=" + p.dir,
"--username=" + p.chainSvr.user,
"--password=" + p.chainSvr.pass,
"--rpcconnect=" + p.chainSvr.connect,
"--rpclisten=:" + p.port,
"--rpccert=" + p.chainSvr.certPath,
"--rpckey=" + p.chainSvr.keyPath,
}
// Launch btcwallet in background
cmd := exec.Command("btcwallet", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
log.Printf("Cannot launch btcwallet: %v", err)
}
btcdArgs := []string{
"--simnet",
"-u" + defaultChainServer.user,
"-P" + defaultChainServer.pass,
"--rpccert=" + defaultChainServer.certPath,
"--rpckey=" + defaultChainServer.keyPath,
"--profile=",
}
// Launch btcd in background
log.Println("Starting btcd on simnet...")
btcd := exec.Command("btcd", btcdArgs...)
if err := btcd.Start(); err != nil {
log.Fatalf("Couldn't start btcd: %v", err)
}
// Create and start RPC client.
rpcConf := rpc.ConnConfig{
Host: "localhost:" + p.port,
Endpoint: "ws",
User: p.chainSvr.user,
Pass: p.chainSvr.pass,
Certificates: p.chainSvr.cert,
DisableAutoReconnect: true,
}
connected := make(chan struct{})
var firstConn bool
ntfnHandlers := rpc.NotificationHandlers{
OnBtcdConnected: func(conn bool) {
if conn && !firstConn {
firstConn = true
connected <- struct{}{}
}
},
}
// The RPC client will not wait for the RPC server to start up, so
// loop a few times and attempt additional connections, sleeping
// after each failure.
var client *rpc.Client
var connErr error
for i := 0; i < connRetry; i++ {
if client, connErr = rpc.New(&rpcConf, &ntfnHandlers); connErr != nil {
time.Sleep(time.Duration(i) * 50 * time.Millisecond)
continue
}
break
}
<-connected
if err := client.CreateEncryptedWallet(p.walletPassphrase); err != nil {
if err := cmd.Process.Kill(); err != nil {
log.Printf("Cannot kill wallet process after failed "+
"wallet creation: %v", err)
}
return
}
// works
addr, err := client.GetNewAddress()
if err != nil {
log.Printf("%s: Cannot create address", rpcConf.Host)
return
}
log.Printf("addr: ", addr)
// shutdown btcd, btcwallet
if err := btcd.Process.Signal(os.Interrupt); err != nil {
log.Printf("Cannot kill btcd process: %v", err)
return
}
if err := cmd.Process.Signal(os.Interrupt); err != nil {
log.Printf("Cannot kill btcwallet process: %v", err)
return
}
// hangs
btcd.Wait()
cmd.Wait()
addr, err = client.GetNewAddress()
if err != nil {
log.Printf("%s: Cannot create address", rpcConf.Host)
return
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment