Proof-of-concept of a cryptocurrency implemented on top of the blockchain
app. The goal is to keep it as simple as possible but complete enough to understand how most cryptocurrencies such as Bitcoin or Ethereum work.
Setup a blockchain as explained in the main readme
On startup, each node generates a wallet (a private/public key pair and an address derived from the public key):
$node1> Token.address
"20902B4FF51658B9CA7C3604F8A5F7F40B9B156C" # node1 address
Each node starts with 0 token (nothing surprising here, the only block in the blockchain is the genesis block, there is no transaction):
$node1> Token.balance()
0
To "inject" tokens in the system we need to cheat and use a forbidden API:
$node1> Token.free_tokens(20) # this will give node1 20 tokens
[...]
$node1> Token.balance()
20
The free_tokens/1
function writes a particular transaction into the blockchain, that gives tokens to the calling node.
Now that tokens are in the system, we can start exchanging it between the nodes of our network using the send/2
API:
# get back the address of node3
$node3> Token.address()
"9F90526460468618E54B49CC11E7473778BE7288"
# from node1 make a transaction of 10 tokens to node3
$node1> Token.send(10, "9F90526460468618E54B49CC11E7473778BE7288")
[...]
# check new balances
$node1> Token.balance()
10
$node3> Token.balance()
10
In this implementation, a block (of the blockchain) only contains one transaction (which is not the case in a real life implementation). You can use the Blockchain.blocks/0
API to see the blocks that get mined into the blockchain.
A wallet contains 3 fields, ECDH keys (public_key
and private_key
) and address
. The address is a public key hash without the base56 encoding.
A transaction contains a list of inputs (an input points to a transaction output), a list of outputs (recipients of the transaction and the amount of tokens), a public key (public key of the sender), a signature (computed from the sender private key) and a hash.
To be validated and added to the blockchain transactions must be verified. Checkout the Transaction.Verify.verify_transaction/2
function to see what happens.
Cryptocurrencies and blockchains are different concepts eventough they often get confused. In this implementation, the Ledger
module abstracts the blockchain so it is seen as a simple list of transactions while still relying on blockchain immutability properties.