Delboy’s Bitcoin Blog

Late 2017. I now find myself inundated with messages from people that want to know about Bitcoin. So instead of repeating myself over and again, I decided to write this blog post.

What is Bitcoin

It’s like emailing money. Transactions are sent from one address to another.  The difference being that there is no central authority verifying the transactions. To be able to securely send coins to each other without the need of a trusted third party like the banks (who incidentally, aren’t to be trusted!*) has been a problem that has been solved by the “Blockchain”, the underlying technology behind Bitcoin.

What is the Blockchain?

The Blockchain is nothing more than a trusted ledger of transactions. It’s a public online bank statement, recording money in and money out from all the different bitcoin addresses (bank accounts).

The computers with the Bitcoin server installed that process all the transactions, do insanely difficult mathematics in order to solve a puzzle, and are racing against each other to be the first to find the answer. The computer that finds the answer has ‘struck gold’ and mints 12.5 BTC into the system, and another block of transactions are recorded on the blockchain.

There will only ever be 21 million Bitcoin, and I believe around 15 million have already been ‘mined’. Many miners combine their computing power in a ‘mining pool’, which shares their part of the 12.5BTC mining reward for doing the calculations and verifying the transactions.

Each block in the chain gets mined every ten minutes, on average. If blocks start being mined too quickly (or too slowly), the difficulty of the math problem the computers need to solve is adjusted accordingly.  So adding faster hardware is pointless, as the software adjusts to make it a waste of time. This is the reason Bitcoin now uses more electricity than several countries!

Never mind that, I want some, what now?

There are various ways of holding bitcoin. The first thing you need to worry about is downloading a wallet.

Pick whatever suits your computer here: https://bitcoin.org/en/choose-your-wallet

The SAFEST way of keeping your Bitcoin safe is by opening the freshly installed wallet, taking a note of the public address, and the private key. There will be an export private key function. Open the exported text file and write the private key down on paper! Then delete everything from your computer! You can still send money to your wallet by giving people your public address, but you cant spend it again until you re-import the private key back into a wallet! So it’s the best way to keep savings.

If you want to spend and use your bitcoin you should leave it installed obviously. It’s better having a wallet on your computer than it is on your phone, or through a website, for the simple reason that the website is someone else’s computer, and that the phone app gets info from someone else’s website too. You will have accounts on websites however that come with a bitcoin address, but be sure to get the one on your computer set up, being your ‘withdrawal address’, and the one you hold the keys for.

Right I have a wallet, what now?

Other than dealing face to face with someone, you buy your Bitcoin from a trading exchange, like any other stock market. Good exchanges for the UK and Europe include Coinbase and Kraken. There’s a pain in the ass verification process to hook your bank account up, but when you do, you can deposit and then buy!

It’s a trading exchange, so you can also sell! Anyway, the website will show your balance, wether in euros, pounds, dollars, or BTC. But you want to withdraw from the website and send it to the wallet you set up earlier.

The Quick way

You can still get your hands on Bitcoin, and indeed trade with Bitcoin, without the annoying verification process. However, you can’t get it back out in GBP or EUR if you haven’t.

I have used Bittylicious several times to buy Bitcoin. You send a bank transfer yourself via digital banking, and the website sees it and sends your coins immediately.

I also use Wex for trading, they allow you to deposit and trade BTC for USD without verification. So long as you withdraw in BTC they don’t care. Like I said though Coinbase or Kraken is the one to use if you intend to cash in one day!

If you have any questions, fire them across and I’ll update this blog post!

Feel free to donate 1De1boyXJzdk4TYmHkR3st6dJmHuEaneHB

Advertisements

Stop git committing chmod changes

Pretty self explanatory. Just do this:

git config core.fileMode false

The documentation says this about it:

core.fileMode 
If false, the executable bit differences between the index and the 
working copy are ignored; useful on broken filesystems like FAT. 
See git-update-index(1). True by default.

Here’s a warning from a guy on StackOverflow:

core.fileMode is not the best practice and should be used carefully. This setting only covers the executable bit of mode and never the read/write bits. In many cases you think you need this setting because you did something like chmod -R 777, making all your files executable. But in most projects most files don’t need and should not be executable for security reasons.

The proper way to solve this kind of situation is to handle folder and file permission separately, with something like:

find . -type d -exec chmod a+rwx {} \; # Make folders traversable and read/write
find . -type f -exec chmod a+rw {} \; # Make files read/write

If you do that, you’ll never need to use core.fileMode, except in very rare environment.

Setup HATEOAS hal+json API responses

I’m busy setting up HAL on our API (see the spec here http://stateless.co/hal_specification.html), which we’re building in Symfony 3. We have used the FOSRestBundle, and JMS Serialiser to set up the API to begin with, and the incredible Swagger for documenting it.

If you aren’t using Symfony, you can integrate this package yourself:

composer require willdurand/hateoas

And if you do use Symfony, there’s a bundle.

composer require willdurand/hateoas-bundle

Register the bundle in app/AppKernel.php.

// .. in array of bundles
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),

Self Link

Open your entity, add the use statement,  and edit the class DocBlock:

use Hateoas\Configuration\Annotation as Hateoas;
@Hateoas\Relation("self", href = "expr('/employees/' ~ object.getId())")

This annotation says that the REST link to an employee is /employees/:id.

Collections with pagination links

Here’s a testAction I made in my EmployeeController:

/**
 * @Rest\Post("/employees/test/test")
 *
 * @SWG\Post(
 *     path="/employees/test/test",
 *     description="Fake call for testing purposes",
 *     operationId="test",
 *     produces={"application/hal+json"},
 *     tags={"employees"},
 *     @SWG\Parameter(
 *         name="page",
 *         in="query",
 *         type="integer",
 *         description="the page you want",
 *         required=false,
 *         default=1
 *     ),
 *     @SWG\Parameter(
 *         name="limit",
 *         in="query",
 *         type="integer",
 *         description="the number of results per page",
 *         required=false,
 *         default=1
 *     ),
 *     @SWG\Response(
 *         response=200,
 *         description="Returned when successful",
 *         @SWG\Schema(ref="#/definitions/listEmployee")
 *     ),
 *     @SWG\Response(
 *         response="default",
 *         description="unexpected error",
 *         @SWG\Schema(
 *             ref="#/definitions/ErrorModel"
 *         )
 *     )
 * )
 *
 *
 * @return PaginatedRepresentation
 */
public function testAction(Request $request)
{
    $page = $request->get('page') ?? 1;
    $numPerPage = $request->get('limit') ?? 1;

    $co = new Company();
    $co->setName('KGB Inc.')
       ->setCode(999999.1);
    $employee = new Employee();
    $employee
        ->setCompany($co)
        ->setId(666)
        ->setEmployeeId(999)
        ->setName('Vladimir Putin');

    $collection = new EntityCollection();
    $collection->add($employee);

    $co = new Company();
    $co->setName('MAGA Inc.')
       ->setCode(999999.1);
    $employee = new Employee();
    $employee
        ->setCompany($co)
        ->setId(999)
        ->setEmployeeId(666)
        ->setName('Donald J Trump');

    $collection->add($employee);

    $numPages = ceil (count($collection) / $numPerPage);

    $filter = new CollectionFilter();
    $filter->getPaginationFilter()
        ->setNumPerPage(1)
        ->setPage($page);

    $collection = $filter->filterArrayResults($collection->toArray());

    $halCollection = new CollectionRepresentation(
        $collection,
        'employees',
        'employees'
    );

    $pager = new PaginatedRepresentation(
        $halCollection,
        'test',
        array(),
        $page,
        $numPerPage,
        $numPages
    );

    return $pager;
}

There’s quite a bit here, but let me explain.

The @Rest\Post(“/employees/test/test”) annotation is the FOSRestBundle. When we call thae URL, it ensures we send POST otherwise we get a 405 response.

The @SWG stuff is Swagger documentation annotation, which hopefully should be self explanatory. The only part you might question is the Schema, which you docblock annotate in the entity class itself. See full Swagger docs for that, but here’s our annotation for a single employee:

* @SWG\Definition(
*   definition="singleEmployee",
*   type="object",
*   allOf={
*       @SWG\Schema(
*           @SWG\Property(property="id", type="integer"),
*           @SWG\Property(property="employeeId", type="integer"),
*           @SWG\Property(property="name", type="string"),
*           @SWG\Property(property="firstName", type="string"),
*           @SWG\Property(property="company",type="object", ref="#/definitions/singleCompany"),
*           @SWG\Property(property="functionDescription", type="string"),
*           @SWG\Property(property="nationalRegisterNumber", type="string"),
*       ),
*   }
* )

@return PaginatedRepresentation returns our collection, wrapped in HAL stuff now.

In the method itself, I create two fake employees (Trump & Putin), add them to the EntityCollection, then I run CollectionFilter on it (https://github.com/delboy1978uk/collection-filter, which I made last week as a filter/paginator system for working with full resultsets). So the interesting bit is $halCollection & $pager. We pass our $collection into CollectionRepresentation, and pass that into PaginatedRepresentation.

So now, we go to https://api.yoursite.com/docs, try our endpoint, and you should see…

Screen Shot 2017-10-30 at 4.43.34 PM

Have fun! 😀

console.log(everything)

I’m currently adding a javascript feature to a page of a site that’s terribly designed (runs on an ancient PHP CMS built in the year 2000 in PHP 4), and terribly implemented, with far too much going on in a way that it shouldn’t.

Anyway, I wanted to see if there was already a javascript value set for the data I required. Here’s how you dump every single JS variable to the console.log() :

for (var b in window) { 
    if (window.hasOwnProperty(b)) {
        console.log(b); 
    }
}

 

Creating custom annotations in Symfony 3

I’m currently building a backend API for a site which requires requests to be signed with an access token header. My problem is, the default @Security annotation feature doesn’t fit with our requirements, because we don’t actually have any users on our site! We actually consume our clients SOAP service, which is where all the important data is stored.

Currently, in a typical controller action, I have the following code:

/**
 *@Rest\Put("/auth/change-password")
 */
public function changePasswordAction(Request $request)
{
 $tokenId = $paramFetcher->get('token');
 $tokenSvc = $this->get('Our\SuperbBundle\Service\TokenService');

 // Check the token exists and is valid
 // throws exception if not found or expired
 $tokenSvc->findToken($tokenId); 
 // actual change password logic here
}

We are going to have several controllers with multiple calls, so we don’t want to add this in every single controller action, so we will create our own custom annotation.

<?php

namespace Our\CustomerZoneBundle\Annotation;

/**
 * Class SecureToken
 * @package Our\CustomerZoneBundle\Annotation
 * @Annotation
 */
class SecureToken
{
}

The next thing we do is create an Annotation listener, which I’ll explain below:

<?php

namespace Our\CustomerZoneBundle\EventListener;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Util\ClassUtils;
use Our\CustomerZoneBundle\Annotation\SecureToken;
use Our\CustomerZoneBundle\Model\Exception\TokenException;
use Our\CustomerZoneBundle\Service\TokenService;
use ReflectionClass;
use ReflectionObject;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

class SecureTokenAnnotationListener
{
    /** @var AnnotationReader $reader */
    protected $reader;

    /** @var RequestStack $requestStack */
    protected $requestStack;

    /** @var TokenService $tokenService */
    protected $tokenService;

    /**
     * SecureTokenAnnotationListener constructor.
     * @param AnnotationReader $reader
     * @param RequestStack $stack
     * @param TokenService $tokenService
     */
    public function __construct(AnnotationReader $reader, RequestStack $stack, TokenService $tokenService)
    {
        $this->reader = $reader;
        $this->requestStack = $stack;
        $this->tokenService = $tokenService;
    }

    /**
     * @param FilterControllerEvent $event
     */
    public function onKernelController(FilterControllerEvent $event)
    {
        $controller = $event->getController();
        /*
         * $controller passed can be either a class or a Closure.
         * This is not usual in Symfony2 but it may happen.
         * If it is a class, it comes in array format
         *
         */
        if (!is_array($controller)) {
            return;
        }

        /** @var Controller $controllerObject */
        list($controllerObject, $methodName) = $controller;

        $request = $this->requestStack->getCurrentRequest();
        $cookies = $request->cookies;
        $mkzCookie = $cookies->get('mkz');

        // Override the response only if the annotation is used for method or class
        if ($this->hasSecureTokenAnnotation($controllerObject, $methodName)) {
            try {
                if (!$mkzCookie) {
                    throw new TokenException(TokenException::ERROR_NOT_FOUND, 404);
                }
                $this->tokenService->findToken($mkzCookie);
            } catch (TokenException $e) {
                throw new AccessDeniedHttpException($e->getMessage(), $e);
            }
        }
    }

    /**
     * @param Controller $controllerObject
     * @param string $methodName
     * @return bool
     */
    private function hasSecureTokenAnnotation(Controller $controllerObject, string $methodName) : bool
    {
        $tokenAnnotation = SecureToken::class;

        $hasAnnotation = false;

        // Get class annotation
        // Using ClassUtils::getClass in case the controller is an proxy
        $classAnnotation = $this->reader->getClassAnnotation(
            new ReflectionClass(ClassUtils::getClass($controllerObject)), $tokenAnnotation
        );

        if ($classAnnotation) {
            $hasAnnotation = true;
        }

        // Get method annotation
        $controllerReflectionObject = new ReflectionObject($controllerObject);
        $reflectionMethod = $controllerReflectionObject->getMethod($methodName);
        $methodAnnotation = $this->reader->getMethodAnnotation($reflectionMethod, $tokenAnnotation);

        if ($methodAnnotation) {
            $hasAnnotation = true;
        }

        return $hasAnnotation;
    }
}

Our event listener uses the annotation reader class, and takes the request object. When the event triggers, the onKernelController() method is called, where we get the Access Token cookie from the request. Then it checks for the @SecureToken annotation, which can either cover an entire class, or can be set in individual method docblocks.

Next, we hook up the service autowiring in the config services.yml:

our.event_listener.secure_token:
    class: Our\CustomerZoneBundle\EventListener\SecureTokenAnnotationListener
    autowire: true
    tags:
        - { name: kernel.event_listener, event: kernel.controller }

Symfony autowiring is pretty cool. the autowire true key allows Symfony to take care of object instantiation, so we don’t even need to fetch the annotation reader or request for the constructor!

Finally, we add our annotation to our method, and remove our check from inside the method:

/**
 * @Rest\Put("/auth/change-password")
 * @SecureToken
 */
public function changePasswordAction(Request $request)
{
    // actual change password logic here
}

Now using whatever HTTP client you like (POSTman 😉 !) when we add our Access Token cookie header, the check happens automatically! Removing the cookie now gives us a 403 response! Success! Have fun! 😀

Codeception Acceptance tests with Javascript

I had an issue on this old legacy site in work where I was writing a basic acceptance test where it clicks all the links in the top section of the home page. The problem was that one of the links opened another window using JavaScript. So I had to reconfigure Codeception to get it running.

There are various different drivers that codeception uses, PhpBrowser which doesn’t do JS, Selenium WebDriver does, and you have several options; you could install Selenium, chrome headless browser, or phantomjs. I chose phantomjs, as it was easiest (for me) to get up and running on a non X Server.

First up, you’ll need phantomjs. Go download it, unpack the zip, move the folder somewhere, and then symlink the bin/phantomjs to /usr/bin/phantomjs.

Next, launch phantomjs like so:

phantomjs --webdriver=4444 --ignore-ssl-errors=true --ssl-protocol=any

Now, in your YAML:

# Codeception Test Suite Configuration

# suite for acceptance tests.
# Run the following command FIRST:
# phantomjs --webdriver=4444 --ignore-ssl-errors=true --ssl-protocol=any

# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.

class_name: WebGuy
modules:
     enabled:
         - WebDriver
         - WebHelper
     config:
         WebDriver:
             url: 'https://USER:PASS@YOUR_URL_HERE'
             browser: phantomjs
             capabilities:
                 acceptSslCerts: true

If you have a site using HTTP Basic Auth, put USER:PASSWORD@ in yopur URL, if not, remove it.

Now in your acceptance test, you can write:

$i->click('Nouvel abonnement');
$i->switchToWindow('webformswin');

Note that, in your Javascript, when you run the open window function, you specify a name. This is the name you use, and not the title from the HTML <head> section!

And there you have it! We can now test with javascript functionality!