Part 20: cyphernode III

cryptoskillz
Bitcoin e-commerce development
8 min readAug 26, 2019

Playing with Docker and Lightning

Preamble

This article aims to play with “Lightning” on the “cyphernode” backend as well as explorer “docker” and figure out how it all works with the proxy etc. Now, let us be upfront and clear we know nothing about “docker” we will be learning and as we go and making a lot of mistakes and most probably doing everything wrong but that is ok, that is how we learn.

Also, this is not essential reading as it is purely a research article offering tertiary information on our journey. If you like minuta then I am pretty sure you will enjoy this, for everyone else please just move on to the next article.

Introduction

This guide aims to program a website to accept Bitcoin. In the previous tutorial, we integrated “cyphernodeinto our “ECS” (without “Lightning”). This time we are going to integrate “Lightning” and ties it into “ECS”.

Installing cyphernode

We have done this a few times already so there is no reason to document the steps here again please refer to “part 18” for installation instructions. Note we are still on testnet but you may install testnet or mainnet.

Note, Presently you have to run a full node that is not pruned for “Lightning” support so please make sure that you have 350gig of hard drive space available. Since “Bitcoin Core 0.16.0” with the introduction of “BIP 159” you have been able to run “Lightning” in a pruned node and “cyphernode” runs “Bitcoin Core 0.18.0” so we are sure that support for this will come soon.

Starting cyphernode

The first thing to do, as always is to start “cyphernode” and you do that by type the following command in the “cyphernode” installation directory.

./start.sh

First things first let us try the standard curl call we use to test things are running as excepted. Run the following command in terminal enter the password you set for RPC whilst setting up cyphernode.

Note, we are using testnet so the port at the end is 18332 if you selected mainnet then you will have to change this to 8332.

curl --user admin  --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": [] }'     -H 'content-type: text/plain;' http://127.0.0.1:18332/

and you will get the following response.

Using Docker with cyphernode

Now let us test it by typing the command in the docs which can be found here.

The first command they list is this

echo "GET /getbestblockinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -

Which will provide the following output

We are not 100% sure how this is working but we do know what is is doing it is running the proxy node in “alpine” which is a minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!. Then it makes the API call (getbestblockinfo) through the proxy.

Ok, cool so now let us see what getbestblockinfo is by looking at the cyphernode “API reference” which show the following

Get the Best Block Info (called by application)

Returns best block info: calls getblockinfo with bestblockhash.

as you can see sho the “API reference there are a number of API calls that we can take advantage of and a few more in “V1 of the API which as far as we can tell is not being used yet but it may be.

Alright now, let us run the other commands in the documentation to make sure the above was not a fluke.

getbalance

echo "GET /getbalance" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -

getbestblockhash

echo "GET /getbestblockhash" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -

getblockinfo

echo "GET /getblockinfo/00000000a64e0d1ae0c39166f4e8717a672daf3d61bf7bbb41b0f487fcae74d2" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -

ln_getinfo

echo "GET /ln_getinfo" | docker run --rm -i --network=cyphernodenet alpine nc proxy:8888 -

Wow, it works (awesome) so we can push any command in the API reference and get a response that way, very cool.

To app or not to app

Now we have the above working we have a clear inflection point we can use the above infrastructure and rebuild “ECS” as a “cyphernode” app, this is clearly the way want us to do and it and the way it has been built the framework is in place to allow us to do this fairly easily. However we want “ECS” to be agnostic we want it to work with “cyphernode”, “casa, “nodl” and whatever else is out there and to build the apps this way would seriously curtail our ability to do this.

Also, we suck at using “Docker” at the moment so would not be confident everyone would not laugh at us if we attempted a 100% “docker” implementation :]

playing with docker

right the first thing we want to do is see what is running we do this by running the “list containers command as shown below:

docker ps

You will get an output like the one below

as you can see all of the containers (cyphernode/bitcoin:v0.18.0) are running so let us see if we can talk to one of them.

get getblockchaininfo

We know that “bitcoin-cliis running on the cyphernode/bitcoin:v0.18.0 so let us see if we can get that to give us some blockchain info. We can do this br running the “docker exec” command. First cop the container ID from the output of docker ps. and type the following command:

docker exec 24efdf4f691a bitcoin-cli getblockchaininfo

and you should get the following output

Awesome, so we can use the “bitcoin-clivia docker.exec or the curl method which is awesome.

get lightning info

Now, we are getting somewhere so now let us see if we can do the same with “lightning”. Run the following command with the “lightning” container ID.

docker exec cf0b5d94ab8d lightning-cli

you will get the following output

Hmm, that did not work as “Lightning” requires the working directory and we are not 100% sure where that is, no worries “grep” to the rescue. Run the following command.

docker exec cf0b5d94ab8d grep .lightning

This will tell us that “Lightning” is in the following directory .lightning so let us set that directory and try again by typing the following command.

docker exec cf0b5d94ab8d lightning-cli --lightning-dir=.lightning getinfo

and we will get the following output

Yay, it works.

accessing the containers via the proxy

Just for fun let us see if we can use the proxy. I say for fun as we will most likely be bypassing this for usecase when it gets to production.

we can do this by running the following command of course you can use any of the API endpoints as described aboce

docker exec 2b62aa57aa95 curl http://proxy:8888/getbestblockinfo

and you will get the following result

docker final thoughts

To be fair docker is pretty cool once you get over the insane learning curve as we can see us using it more at cryptoskillz towers in the future.

One thing we are not able to do yet is run an exec command with the container name instead of the container ID. We know for sure this is possible but we are just to dumb to have figured it out (just yet). This is a real problem as container IDs change on every start and stop.

Using Docker commands with ECS

So now we have docker up and running it would be really cool if we could interface with it via “ECS” luckily we can do that.

The latest branch that deals with code in this tutorial can be found “here

Database base changes

None

Code Changes

we installed a new package called “docker-cli-js” to handle our interactions with docker.

light.js

This a new file we created (just for testing) we have not integrated into “ECS” any more than this at this moment of time.


var dockerCLI = require("docker-cli-js");
var DockerOptions = dockerCLI.Options;
var Docker = dockerCLI.Docker;
var docker = new Docker();
//call lightning container get info command
docker.command('exec 99a7103d7ab9 lightning-cli --lightning-dir=.lightning getinfo', function (err, data)
{
console.log('data = ', data);
});
//call the proxy server to the get the balance
docker.command(
'exec eaf667a5b8be curl -H "content-type: text/plain;" http://127.0.0.1:8888/ln_getinfo',
function(err, data) {
console.log("data = ", data.raw);
}
);
//calling the proxy server to get a balance
docker.command(
'exec eaf667a5b8be curl -H "content-type: text/plain;" http://127.0.0.1:8888/getbalance',
function(err, data) {
console.log("data = ", data.raw);
}
);

Let us take a look and see what is happening with the above.

The first block of code set up the docker package.

var dockerCLI = require("docker-cli-js");
var DockerOptions = dockerCLI.Options;
var Docker = dockerCLI.Docker;
var docker = new Docker();

next, let us call the lightning container and get the info

//call lightning container get info command
docker.command('exec 99a7103d7ab9 lightning-cli --lightning-dir=.lightning getinfo', function (err, data)
{
console.log('data = ', data);
});

Now, let us do the same thing but this time via the proxy

//call the proxy server to the get the balance
docker.command(
'exec eaf667a5b8be curl -H "content-type: text/plain;" http://127.0.0.1:8888/ln_getinfo',
function(err, data) {
console.log("data = ", data.raw);
}
);

Lastly, let us use the proxy to get the Bitcoin balance

//calling the proxy server to get a balance
docker.command(
'exec eaf667a5b8be curl -H "content-type: text/plain;" http://127.0.0.1:8888/getbalance',
function(err, data) {
console.log("data = ", data.raw);
}
);

As you can see the commands above are exactly the same as we did from the command line (which is neat) so if we decide to go down this route (via proxy etc) it will be fairly trivial to implement.

Conclusion

There we have it, we have configured and implemented cyphernode into our overall software stack and interfaced it into “ECS”. This gives us a really powerful boost to our back end infrastructure. But, to level with you, this was one of the hardest things we have done yet in this series and I think a lot of that can be attributed to our lack of Docker knowledge.

Next time we will look to host “ECS” and cyphernode on a “digitalocean server.

--

--