цифровая электроника
вычислительная техника
встраиваемые системы

 
» » Как создать свой блокчейн: код блокчейна в 100 строк

Как создать свой блокчейн: код блокчейна в 100 строк

Автор: Mike(admin) от 30-10-2017, 19:35

Что такое блокчейн?


Блокчейн сегодня считается перспективной и прорывной технологией, благодаря которой можно организовать не только финансовые операции с участием криптовалют, но и многие другие процессы социальной, экономической и производственной областей человеческой жизнедеятельности. Подробно о том, что такое блокчейн, и каковы его принципы работы можно прочитать здесь.


Как создать свой блокчейн

С технической точки зрения, блокчейн – это распределенная база данных со специальными функциями, такими как проверка, хранение и синхронизация данных. С точки зрения бизнеса, это концепция, которая позволяет проводить эффективные и надежные одноранговые транзакции, не требуя центральной точки контроля. Впрочем, существуют некоторые отличия блокчейна по сравнению с распределенной базой данных. В Blockchain можно только добавить информацию, затем данные проверяются и подписываются. Но как же создать блокчейн? В данном материале мы рассмотрим как запрограммировать свой блокчейн примерно в 100 строках кода, используя язык программирования javascript.


Программная архитектура блокчейна


Blockchain – это цепочка блоков. Чтобы было все как можно проще, но не слишком простым, каждый блок включает в себя наиболее необходимые элементы: индекс, временную метку, данные, хэш и предыдущий хэш. И каждый новый блок, который должен быть добавлен в цепочку, также должен быть проверен.



import CryptoJS from 'crypto-js';

import chain from './chain';

export const calcHash = ({index, prevHash, timestamp, data}) => {
    return CryptoJS.SHA256(index + prevHash + timestamp + data).toString();
}

export const create = (data) => {
    const prev = chain.last();
    const index = prev.index + 1;
    const timestamp = new Date().getTime();
    const prevHash = prev.hash;
    const hash = calcHash({ index, prevHash, timestamp, data });

    return { index, timestamp, data, prevHash, hash };
};

export const isNewBlockValid = (newBlock, prevBlock = chain.last()) => {
    let isValid = true;

    if (prevBlock.index + 1 !== newBlock.index) {
        console.log('New block has invalid index');
        isValid = false;
    } else if (prevBlock.hash !== newBlock.prevHash) {
        console.log('New block has invalid prevHash');
        isValid = false;
    } else if (calcHash(newBlock) !== newBlock.hash) {
        console.log('New block has invalid hash');
        isValid = false;
    }

    return isValid;
};

Цепочка блоков – это одноэлементная реализация, которую вы разрешаете расширять с помощью нового проверенного блока и заменяете цепочку в случае соединения нескольких одноранговых узлов, выбирая ту, которая имеет самое длинное количество блоков в ней.



import { calcHash, isNewBlockValid } from './block';

const Chain = (function () {
    let instance;
    const origin = {
        index: 0,
        timestamp: 0,
        data: 'Hello Blockchain!',
        prevHash: 0,
        hash: calcHash({ index: 0, prevHash: 0, timestamp: 0, data: 'Hello Blockchain!' })
    };
    const chain = [origin];

    function isChainValid(newChain) {
        let isValid = true;

        if (JSON.stringify(newChain[0]) !== JSON.stringify(origin)) {
            console.log('Received chain is invalid. Origin block does not coincide');
            isValid = false;
            return isValid;
        }

        const tempChain = [newChain[0]];
        for (let i = 1; i < newChain.length; i += 1) {
            if (isNewBlockValid(newChain[i], tempChain[i - 1])) {
                tempChain.push(newChain[i]);
            } else {
                isValid = false;
                return isValid;
            }
        }

        return isValid;
    }

    function get() {
        return chain;
    }

    function update(block) {
        if (isNewBlockValid(block)) {
            chain.push(block);
        }
    }

    function last() {
        return chain.slice().pop();
    }

    function replace(newChain) {
        if (isChainValid(newChain) && newChain.length > chain.length) {
            console.log('Received chain is valid. Replacing current chain with received chain');
            chain.length = 0; // clear current chain
            chain.push(...newChain); // fill current already empty chain with the new one if valid
        } else {
            console.log('Received chain is invalid');
        }
    }

    function create() {
        return { get, update, last, replace };
    }

    return {
        init() {
            if (!instance) {
                instance = create();
            }
            return instance;
        }
    };
}());

export default Chain.init();

Существенной особенностью узла является совместное использование и синхронизация цепочки с другими узлами. Когда узел генерирует новый блок, он передает его в сеть. Когда узел подключается к новому одноранговому узлу, он запрашивает последний блок. И когда узел встречает блок с индексом, большим, чем текущий известный блок, он либо добавляет блок своей текущей цепочке, либо запросы для полной цепочки блоков. Нет автоматического обнаружения сверстников. Местоположение (URL-адресов) одноранговых узлов добавляется вручную.



import express from 'express';

import chain from '../chain';
import { create } from '../block';
import sockets from '../p2p/sockets';
import { connectToPeers } from '../p2p/index';
import { broadcast } from '../p2p/handlers';
import { responseLatestMsg } from '../p2p/actions';

const router = express.Router();

router.get('/health-check', (req, res) =>  res.send('OK'));

router.get('/chain', (req, res) => {
    res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify(chain.get()))
});

router.post('/mine', (req, res) => {
    const block = create(req.body.data);
    chain.update(block);
    broadcast(responseLatestMsg());
    console.log('New block in chain has been added: ', block);
    res.send(block);
});

router.get('/peers', (req, res) => {
    res.send(sockets.get().map(s => `${s._socket.remoteAddress}:${s._socket.remotePort}`));
});

router.post('/connect', (req, res) => {
    const { peer } = req.body;
    connectToPeers([peer]);
    console.log('New peer in p2p websocket has been added: ', peer);
    res.send(peer);
});

export default router;

Пользователь может управлять узлом с помощью HTTP-сервера, чтобы отображать все блоки в цепочке, создавать новый с содержимым, заданным пользователем, и добавлять одноранговые узлы. Следует отметить, что узел предоставляет два веб-сервера: один для пользователя для qp-управления узлом (HTTP-сервером) и один для одноранговой связи между узлами (сервер Websocket P2P). Дополнительную информацию по реализации такого блокчейна можно найти на github.com/stremann/chainpro.




Теги: блокчейн, криптовалюты




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий