While streaming, a brilliant visitor suggested we write a blockchain in Python.

So we did it.

Please note there is no validation or simulated voting here.

Here are the results, in `package/blockchain.py`

:

```
from __future__ import annotations
# https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports
from oscrypto.symmetric import aes_cbc_pkcs7_encrypt as encrypt # type: ignore
class Node:
__slots__ = 'prior_node', 'data', 'hash'
prior_node: Node
data: bytes
hash: bytes
def __init__(self, prior_node, key, data):
self.prior_node = prior_node
self.data = data
if prior_node is None:
init_vector = bytes(16)
else:
init_vector = _ensure_byte_length(prior_node.hash, 16)
key = _ensure_byte_length(key, 32)
self.hash = encrypt(key, data, init_vector)(1)
def __repr__(self):
return f'Node<{self.data}n{self.hash}n{self.prior_node}>'
def _ensure_byte_length(bytes_, length):
return bytes(bytes_.ljust(length, b'x00')(:length))
class Chain:
__slots__ = 'nodes'
def __init__(self, key: bytes, data: bytes):
self.nodes = Node(None, key, data)
def __repr__(self):
return f'Chain:n{self.nodes}'
def new_node(self, key, data):
self.nodes = node = Node(self.nodes, key, data)
return node
def __len__(self):
length = 0
nodes = self.nodes
while nodes:
length += 1
nodes = nodes.prior_node
return length
def main():
chain = Chain(b'the key', b'here is a bit of data')
chain.new_node(b'P@$$w0rd', b'and here is a bit more data')
chain.new_node(b'hunter2', b'and finally here is some more')
print(chain)
if __name__ == '__main__':
main()
```

And here is a little test, `tests/test_blockchain.py`

:

```
from package.blockchain import Chain
def test_blockchain():
chain = Chain(b'the key', b'here is a bit of data')
chain.new_node(b'P@$$w0rd', b'and here is a bit more data')
chain.new_node(b'hunter2', b'and finally here is some more')
assert len(chain) == 3
```

Please note that we do require oscrypto and openssl to run this.

Coverage was run with pytest under Python 3.7. He ran with black and mypy too.