How to Run Multiple Geth Instances on a Private Ethereum Blockchain

A private ethereum blockchain with multiple geth instances can be run over a network or on the same computer. We will explain how to do both, and also how to solve some common issues.

Configuring genesis.json

We need to create a JSON file, which will represent the genesis block of our private blockchain. This file which we will name “genesis.json” will be used by all of our nodes, and is in fact what determines which chain that we are on.

The gasLimit allows us to execute contracts, and by setting the mining difficulty extra low we can easily create our own ethers. If you have several computers on a network, copy this file so all of them have the same genesis.json.

Launching Geth

Each geth instance should be run with the following parameters:

geth –genesis <path to genesis.json> –networkid 321 –nodiscover –datadir <path to empty folder> –port 30304 console

What all the instances will have in common is the genesis path and the network identification. The nodes will only attempt to connect to other nodes with the same network identification, but we are also adding a –nodiscover flag to avoid accidentally connecting to nodes outside our network.

Each node will have a different data directory where the blocks data is stored and, if running on the same computer, also a different port. So if you plan on launching several instances on the same computer, you will need an empty folder to be used for each of the nodes.

Windows

If you are running multiple geth instances on a Windows computer, add the flag –ipcdisable, to avoid “Error String IPC: Access is denied”. If you do not want to disable IPC, pick a different IPC path for each node with the flag –ipcpath <path> . The default path is “\\.\pipe\geth.ipc”, so name the second node something else (e.g. “\\.\pipe\geth2.ipc”).

Connecting Geth Nodes to Each Other

In order to explicitly connect one geth node to another, we need its URL. To get it, type the following into a running geth console:

admin.nodeInfo.NodeUrl admin.nodeInfo.enode

It will return something like:

“enode://702de1918184581815e1a00e63d849524cb4126b9b5886090eabd4d4b5dc6f24c4198249775df30f835b1bfbc9a9733c014b27a99008043f3274c22e49db6fca@[::]:30304?discport=0”

The node URL includes a public key, an IP, and a port.

If you are on Windows, you may need to replace the IP part of the enode URL (after the @), with your IP. If both instances are running on the same computer, the IP would be 127.0.0.1, and the URL would be:

“enode://702de1918184581815e1a00e63d849524cb4126b9b5886090eabd4d4b5dc6f24c4198249775df30f835b1bfbc9a9733c014b27a99008043f3274c22e49db6fca@127.0.0.1:30304?discport=0”

Now, on a different geth instance console, type:

admin.addPeer(<enode of first geth>)

To check that indeed the nodes are connected to each other, type web3.net.peerCount in either of them. You
should get “1” as a result.

You can connect as many nodes as you want. Happy testing!

Extra Resources

Check out the the chapter Testing contracts and transactions, about creating accounts and mining in the book Ethereum Frontier Guide, and check Adrian Duke’s guide for pre-seeding accounts using allocation.

Independently Generating Your Private Key for Coinkite

In How to Use Coinkite’s Multi-Signature Wallets with Bitcore we explained how to create a multisignature wallet on Coinkite and cosign it with Bitcore. We used Coinkite’s offline tool to generate a key pair. Although it is easier to use Coinkite to generate the private key, it is a good security practice to generate it independently. Below, we explain how to do this with Bitcore.

In the following dialog choose “Import Key” and you will see the “Import Extended Pubkey” dialog:

multi-signature-key-creation

import-extended-pubkey

Separately, we will have to generate the key and signature with Bitcore and its add-on library Bitcore Message:

This is a sample output:
xprivkey: tprv8ZgxMBicQKsPdhaer1ZSHH2ZU6CbPforhVuVAn6qUgxfdMNLLGRTGM33N5CaSEoLmoB5kZF9w5dXBz12j3WXyTvBMgqap1xwM28gJyooATU
xpubkey: tpubD6NzVbkrYhZ4XAcSjfE2gggg37iXYzzmGoWGTJ98txm4Tqd6xfF3SqeuYCkMNsAKy9hnyJimaMo8FoHkg4DmTpUF4B85nnLfKAWzgq11TJB
Signature for message "Coinkite": H2uhiyw4+FQWRx4mniYVAvPZ+pl7Wmur/IvYOOjAARuFUy9HTXoy6s3J9k7M9QKbCh9GQbPupuNTzjK43ZJZh6U=

With this, you can submit the xpubkey and signature to Coinkite, and store the xprivkey safely on your end.

How to Use Coinkite’s Multi-Signature Wallets with Bitcore (Beginner Friendly Article)

The Bitcoin community has been talking about multi-signature wallets for years. However, it is still very difficult for end users to use these wallets. Multi-signature wallets should allow copayers to communicate, but there is no standard protocol for seamless communication between copayers. The Bitcoin community should standardize the communication process.

We’re going to learn to use a 2-of-3 multisignature wallet with Coinkite’s API and Bitcore. One cosigner will use a Coinkite account, and the other will use the Bitcore library in NodeJS.

Setting Up Your Coinkite Multi-Signature Wallet

First we need to create a multi-signature wallet on Coinkite. Select “Multisig vault” on the Coinkite wallet page.

create-multi-signature-wallet-on-coinkite

Enter an account name and select “Bitcoin Testnet” as currency.

new-shared-account

Choose 2-of-3 (the default value).

setup-account

Now it’s time to configure each cosigner. For the first cosigner, select “Simple”. This cosigner will be controlled by Coinkite, so we name it “Coinkite”.

key-generation

For the second cosigner, select “Generate Key”. Go through the process until you see the screen below. Securely store the “HD Wallet” part. Next, click “Upload to Coinkite”.

private-key

Rename the second cosigner “Bitcore”.

Each of the three cosigners in a 2-of-3 wallet has a private key, however, since two cosigners are sufficient, we will use the third cosigner’s key as a backup. Choose “Passphrase” or “Generate key” and name the third cosigner “Backup”.

copayer-status

Click “Create Shared Account”, accept the warning, and your multisig wallet should be ready.

shared-account-information

The above window shows your balance, your receiving address, and the public keys for each cosigner. Save this page to your bookmarks as it might come in handy later.

API keys

We need Coinkite’s API keys. Go to https://coinkite.com/merchant/api and click “Create New Key”. On the next screen, check the following permissions: read, recv, send, send2, and cosign. Click “Save Changes”.

permissions

You’ll be given an API key and an API secret. Write down the API secret as it’s only shown for a limited time.

Enter NodeJS

So, we’re all set up on Coinkite’s side. We’ll create an empty node project (you need to have NodeJS installed). We need three packages: bitcore, coinkite-javascript and request. In an empty folder, run the command:

npm install bitcore coinkite-javascript request

This will install both of them: request is a widely used package that’s for, you guessed it, making http requests. We will use it to communicate with Coinkite’s API. coinkite-javascript is written by the Coinkite team, and will help us to set the correct headers when making those requests.

The First API Call

To make your first API call, create the file “app.js” containing the code below in your project folder. Don’t forget to enter your own API keys.

Here we’re using the request package to call https://api.coinkite.com/v1/my/self , which is a Coinkite API endpoint, to get general information about your account (view documentation).

We’re using Coinkite’s helper to place the correct authentication headers. When the json option is set to true, the response body is automatically parsed for us.

If you run this node app.js you should get the following response:

My user name is <your username>

The following helper code will allow us to call any Coinkite endpoint and automatically set the correct header. Create a file in the same project folder called “coinkite-helper.js”.

The request function can now be used for any Coinkite endpoint, any HTTP method, and parameters.

Now let’s replace the contents of app.js so it uses this helper function:

If you run the app again, you should get the same result as before.

Cosigning Process

The Coinkite API endpoints we will be using are /v1/new/send and /v1/co-sign (link to this cosigning related ones).

The process of performing a transaction with a 2-of-3 multi-signature wallet on Coinkite is as follows:

  1. Make a send request (using /new/send). You will get tha “CK_refnum” to identify the send request. You can use the detail endpoint with any CK_refnum to see all the information about that object, which could be anything (requests, accounts, cosigners…).
  2. Get the signing requirements for the cosigner we have named bitcore by using /co-sign/<request_refnum>/<cosigner_refnum>.
  3. Ask Coinkite to sign the transaction.
  4. Sign for the “bitcore” user and send the signature via /co-sign/<request_refnum>/<cosigner_refnum>/sign.

Now we will guide you through the code for each of these three steps.

To begin, we need the cosigners refnums. To get them, modify app.js as follows:

Run the script and you should get something like this:

[{“user”:”coinkite”,”refnum”:”1EC3A1CFFE-2DAE34″,”xpubkey”:”tpub⋯ rumgqaM9″},

{“user”:”bitcore”,”refnum”:”1B590633FF-3B60BC”,”xpubkey”:”tpub⋯ ANz6KXnh”}]

Assign this, and list the HD private key we generated at the beginning of app.js to use later:

The “bitcore” user’s xpubkey and xprivkey should be the ones we generated earlier.

Issuing Send Requests

The API endpoint for creating send requests is /v1/new/send. The Coinkite API requires that we use the PUT method and the parameters account, amount, and destination:

In order to try this, your wallet must contain bitcoins. Here’s a faucet that you can use to obtain free testnet bitcoins.

If you try this more than once you might get the error  “No fund sources to draw from (no balance)”. This is because the rest of the funds are being sent to the change address. If this happens, go to the “Pending and Recent Transactions” section at the bottom of https://coinkite.com/accounts/balances to cancel pending requests. The API can also be used to cancel Coinkite requests:

To resume a previous transaction, use the endpoint /v1/list/unauth_sends.

Signatures

Now for the fun part (signing stuff is fun, right?). We will sign the transaction with the Coinkite API and then add another signature with Bitcore.

The first part is pretty straightforward. We can ask Coinkite to sign using the co-sign endpoint. Here we’re using the “cosigners” variable that we defined earlier, which has all the cosigners’ refnums:

You should get the message “Signature added, but further signatures are required.”, along with data related to the transaction at hand.

We will use the “Bitcore” cosigner’s CK_refnum for the other signature. Fetch the signing requirements, sign them, and send the signatures back to Coinkite.

First we request the signing requirements for the “Bitcore” cosigner, then we send the corresponding signatures.

getSignatures

This is the getSignatures function we used above:

There’s a lot going on here so let’s break it down. We need a signature for each input we are sending money from. Coinkite provides all the information we need to generate these signatures except the extended private keys we already have. The full signingInfo structure, available here, provides the following information:

  • sighash: This is what we sign.
  • pathIndex: This is the x value in Coinkite’s m/x derivation path. We use the pathIndex to derive a regular private key from an HD key.
  • address: The input address.We can use the input address to ensure that we generated the correct private key.

We will also need to generate a private key (privKey) for each input. We use Bitcore, our xprivKey and the derivation path provided by Coinkite to do this.

With this private key in hand, we sign the sighash using the bitcore.crypto.ECDSA.sign function. We then assemble a triplet for each input with the corresponding signature, sighash and path index and send it to Coinkite.

Tying It All Together

See our sample code for an example of how to link all of these functions together to perform a transaction from start to finish.

Bonus: How to Generate Addresses for HD Multi-Signature Wallets

Hierarchical Deterministic (HD) wallets generate a new address for each transaction. The only difference in this case is that each of those addresses is multi-signature. A 2-of-3 wallet is associated with three public keys.

To generate each multisig address Coinkite derives regular public keys from the cosigner extended public keys and creates a new multisig address for them:

Multiplexing Online Web Wallets with Bitcore Wallet Service

In Web Wallets Using Copay and Scalable Multi-Signature Web Wallets With Copay we explained how to multiplex Copay connections to form a single BitPay Insight server connection so you could easily scale an online web wallet service based on BitPay open source software. Copay has since been modified to use interesting new components: Bitcore Wallet Service (BWS) and Bitcore Wallet Client. The Bitcore Wallet Client makes it easy to manage multi-signature wallets. However, the client only handles one wallet at a time. If you want to use more than one wallet at a time you must instantiate different clients, each of which uses a different network connection. To get around this new issue and multiplex the connections we have modified BWS and Bitcore Wallet Client.

First, we decoupled the client API class from the physical network socket in the Bitcore Wallet Client. This is transparent to the user of the library. Then we modified the way messages are routed between sockets in the Bitcore Wallet Service to allow more than one wallet per connection. We have submitted two pull requests to integrate these modifications into the BWS and Bitcore Wallet Client:

  1. https://github.com/bitpay/bitcore-wallet-client/pull/89
  2. https://github.com/bitpay/bitcore-wallet-service/pull/272

Resources

Scalable Multi-Signature Web Wallets With Copay

As we saw in Web Wallets Using Copay the main drawback to using BitPay’s Copay as an online web wallet like Coinbase is its lack of scalability. Every Copay wallet establishes two connections to the Insight server. Our previous article includes code which eliminates one of the connections used to send and receive single-signature wallet updates to and from the blockchain. Here we offer code which consolidates all multi-signature wallet copayer updates.

First, a quick explanation of how Copay works. Let’s refer to an instance of Copay running in a web browser as a client, and to the instance of Insight the various clients connect to as server. When a wallet connects to a server it is assigned a channel according to the wallet’s public key. A channel in this context functions similarly to a chatroom; when a message is sent to a channel, it is received by all clients subscribed to that channel. All the users of a specific multi-signature wallet will be assigned the same channel and so receive each other’s messages. Because of the way clients are coded in Copay each socket is subscribed to only one channel but the number of channels a socket may be subscribed to is actually unlimited. Additionally, Copay takes advantage of an Insight plugin called “mailbox” that allows messages between clients to be distributed asynchronously. A client may broadcast a message regardless of whether the other clients are connected at that time. This is used for transaction confirmations and other types of notifications.

What our modification does is separate a wallet from its socket, so several wallets may share the same socket. This single socket will subscribe to the corresponding channel of each wallet. Messages are sent normally, but receiving messages requires a simple bit of routing so the message gets to the right wallet. Note that, because of the way socket channels work, if a socket receives a message, there is a wallet using that socket that should receive that message. Our modification doesn’t increase network traffic.

Bitcoin lacks specifications for joining wallets and receiving new addresses generated by other copayers. Fortunately, Copay has addressed these issues for their users, but the solution should ideally be a standard part of Bitcoin.

(Sebastian Wain contributed with the writing of this article)

Web Wallets Using Copay

Victor Gonzalez from CoinFabrik forked the Copay project and modified the code to facilitate the creation of online wallet services. Currently, the Copay project handles your wallet on your browser, desktop, and mobile devices but not on a Copay server. The new Bitcore Wallet Service does store your wallets on a server, but they are not live: a wallet and the balance it contains are only updated when you use the Bitcore Wallet Client.

Both Bitcore Wallet Service and Copay establish a connection to the Insight server to send and receive information to the blockchain each time a wallet is opened. The key limitation for running multiple wallets on a Copay server is the number of connections to the Insight server. We modified the Copay project code to receive blockchain updates for all the addresses in the different wallets through a single connection to the insight server. Currently, this only works for 1-1 wallets.

We are planning to include multi-signature wallets soon. We will modify the code so that copayers who use online bitcoin wallets also communicate with one another via a single connection shared amongst Insight mailboxes.

Code

The code is available at github.

Prerequisites

MongoDB: This code assumes that mongodb is on localhost. Change this line if you need to point to another host.

Installation

$ git clone https://github.com/CoinFabrik/copay.git
$ cd copay
$ git checkout tags/online-bitcoin-wallets-0.0.1
$ npm install
$ node example.js

Playing with Wallets

The program will prompt the user for an e-mail and password, used for encrypting wallets, and then it will create ten 1-1 wallets.
The program runs a REPL to allow the user to issue commands and query information. For example:

> var wallet = convenience.getAnyWallet()
> wallet.getAddresses()[0]

The above code will print one of the new wallet’s addresses. The user may send some bitcoins to this address.

To spend the bitcoins in the wallet, the user may enter the following command:
> convenience.spend(wallet, <destinationAddress>, <amountInSatoshis>)
To get the balance of the wallet:
> convenience.getBalance(wallet)

Notes

  • MongoDB is used to store both the user’s identity and the wallet. The code can easily be modified to use another database. Additionally, add authentication and encryption to secure the connection between Copay and the database.
  • It is important to note that the bitcoin community is divided on using online wallet services instead of a decentralized wallet since decentralization is at the heart of bitcoin, and online services pose greater security risks.
  • As is the case with any software which will be used to handle other people’s money, a security professional should review any product you develop based on our code.

Resources

If you liked this article, you might also like:

 

Installing Copay in Microsoft Windows

Pure javascript Node.js modules are a charm to install with Node Package Manager (npm). However, you may occasionally have to install a module with Node.js native bindings. The installation is painless if you use Linux but if you are using Windows you will not forget the experience! Below is a step by step guide to installing the multi-signature wallet application Copay or any other application or module that requires the bignum package in Windows.

Prerequisites

  1. Node.js with npm: http://nodejs.org/download/
  2. Python 2.6 (yes, 2.6): https://www.python.org/downloads/windows/
  3. Visual Studio. I used Visual Studio 2012 but it should work with Visual Studio 2010+.
  4. Add Node.js, npm, and Python to your path

Basics

  1. Install the latest OpenSSL Windows binary distribution (Win32 OpenSSL v1.0.1j when this post was written). Use the default path since the bignum modules looks at this path.
  2. Follow the Copay installation instructions and stop before npm start.

Fix

The bignum module referenced by Bitcore inside Copay has a critical bug. It uses the free function to release memory allocated from the OpenSSL library instead of using OPENSSL_free. Follow these steps to fix it:

  1. Edit copay\node_modules\bitcore\package.json
  2. Change the dependencies to point to the latest bignum release (0.9.0 when this post was written)
  3. Go to copay\node_modules\bitcore
  4. Run npm update bignum

You can then run npm start. Don’t forget to start testing with the testnet instead of using real bitcoins!

BitPay Insight API

The BitPay Insight API has the same issue.

Forcing a Specific Visual Studio Version

This is a contribution from Mauro Leggieri: to configure a specific visual studio version you must set the preferred version using SET GYP_MSVS_VERSION=2012

Resources