Creating a simple cryptocurrency: part 4

in #cryptocurrency7 years ago (edited)

Github repository

The repository for scryp is at https://github.com/megacortex/scryp. Github saves snapshots of the repository, making it possible to provide a link corresponding to each step of development. For example, here is the Github snapshot as of part 3, when only the licence and readme.md files were in the repository.

Sending a payment to a server

Now that we have defined the format of a transaction, the next step is to provide a mechanism for clients to send payments to each other. For each payment, the payer must build a transaction, then send it to the alpha server for processing. Eventually both the payer and payee learn if the payment is accepted by monitoring the servers.

We can use the efficient UDP for transmitting payment transactions from clients to servers, because we don't mind occasionally losing one, and because our transactions are small enough. To keep matters simple, we require that servers have an IPv4 address.

Two new node.js programs are in the part 4 repository: pay.js for sending payments and recv.js for receiving them. The former will eventually be incorporated into a full client program and the latter into a full server program. Click on the headings below to see the programs.

pay.js annotation

Starting at line 1, notice the non-Javascript line #!/usr/bin/env node. This allows the program to be started as a shell command $ pay.js ..., rather than the usual $ node pay.js .... The program must be made executable ($ chmod +x pay.js) and either be in a directory specified in the PATH environment variable or a full path must be used (e.g., $ ./pay.js ...).

Moving to line 4, notice the required packages require('string-methods')(require('fs-extra')). This is an npm utility package for convenience. It adds several methods to String.prototype, mostly involving the file system and specifically tailored for this project. All methods are synchronous and errors are handled within the package, usually leading to program termination. Under normal operating conditions the module works silently.

One of these methods is used in line 8: const seed = seedPath.loadData(). seedPath is a string (set to '.seed') and loadData() is a string-methods method which loads data from the .seed file into the seed variable. With no argument, it returns a buffer (raw data) rather a string.

The .seed file must be 32 bytes in length and should be random. One simple way to create it is with $ cat /dev/random | head -c 32 > .seed. This file is equivalent to a password and should be treated as such; it is used to generate the key pair. The secret key is used for signing; without it your account is inaccessible. The public key is needed by others to pay you. So keep a secure copy of it and keep it secret: $ chmod 400 .seed

The next section of code stores command line arguments in variables, with some checking and converting. Two parameters are required: amount and payee. If the IPv4 address (or domain) and port of the alpha server are not also specified, they default to 'localhost' and 6882.

The transaction can then be built as described in part 3.

Finally, the transaction can be transmitted using the node.js UDP module. Transmission can be tested even without recv.js if your system has nc (netcat) and hexdump. Start them like so:

$ nc -ukl 6882 | hexdump -ve '140/1 "%.2x" "\n"'


netcat waits for udp packets on local port 6882. As they arrive, they are converted from 140-byte raw data to 280-hex-digit strings. Try sending test payment transactions to yourself like so (port defaults to 6882):

$ pay.js 100 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef address


where address can be:

  • blank (defaults to localhost)
  • localhost
  • 127.0.0.1 (same as localhost)
  • 192.168.x.y (your LAN address, which you can find here if you don't know it)
  • external IPv4 (as seen from the internet, which you can find here, and which works only with capable routers)

recv.js annotation

This is the counterpart to pay.js, similar but with a few differences.

The UDP section of code opens a listening socket which accepts incoming payment transactions until interrupted. Each transaction is unpacked into the txObj object variable for display and also verified. The unpacking code and associated constants and utility functions are all contained within the ct object. This is a simple technique taking advantage of Javascript objects, rather than using more complex classes, to organize and encapsulate code.

Use it for testing pay.js like so (port defaults to 6882):

$ recv.js


You should see something like this displayed:

{ time: 1497289304245,
  amt: 100,
  payee: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
  payer: '38125d46a22a661b5ceebae73b7f3073592872978d588c36c1a2f2898df15db6',
  raw: <Buffer 00 00 01 5c 9d 65 a8 b5 00 00 00 64 01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef 38 12 5d 46 a2 2a ... >,
  sig: <Buffer b2 9e b0 76 d7 6f 2a 24 46 c1 63 a1 10 fc 78 6b 8d 74 66 be d2 27 4b 36 9d a8 1a 4c 22 2e 90 bb 8e 69 e3 4b 9f ed 56 a2 ad 88 75 68 38 4d 3c bb 02 30 ... > }
verified


< part 3 | part 5 >