웹 프론트엔드 JS 튜토리얼 블록체인 구현을 위한 200줄의 코드 블록체인 예시에 대한 자세한 설명

블록체인 구현을 위한 200줄의 코드 블록체인 예시에 대한 자세한 설명

May 30, 2018 pm 02:15 PM
Blockchain 차단하다

이 글은 블록체인을 구현하기 위한 200줄의 코드를 주로 소개하고 있습니다. 매우 훌륭하고 참고할만한 가치가 있습니다. 필요한 친구들이 참고할 수 있습니다.

블록체인(블록체인, 트랜잭션 체인 블록)의 개념을 이해하는 것은 매우 간단합니다. 분산형(즉, 동일한 시스템이 아닌 다른 네트워크 장치에 배치됨) 데이터베이스는 증가하는 레코드 목록 호스팅을 지원합니다. 그러나 블록체인을 우리가 해결하도록 돕고자 하는 목표와 혼동하기 쉽습니다. 그 순간 사람들의 마음 속에 블록체인이라는 단어는 거래, 계약 또는 스마트 암호화폐의 개념과 매우 밀접하게 연관되어 있습니다.

여기서만 블록체인은 비트코인과 동일하지 않으며, 특히 소스 코드를 기반으로 하는 경우 블록체인의 기본 사항을 이해하는 것이 생각보다 쉽습니다. 이 기사에서는 JavaScript로 200줄의 코드로 구축된 간단한 모델을 제안합니다. 우리가 NaiveChain이라고 부르는 이 프로젝트의 소스 코드는 GitHub에서 찾을 수 있습니다. 1부 및 2부: 기능을 자세히 살펴보고 싶다면 치트 시트를 사용하고 표준 ECMAScript 6을 사용하겠습니다.
블록 구조

1단계 - 블록을 포함해야 하는 요소를 식별합니다. 단순화를 위해 구조적 무결성을 유지하기 위해 기록할 이전 블록의 인덱스(지수), 타임 스탬프(타임스탬프), 데이터(데이터), 해시 및 해시 등 가장 필요한 것만 포함합니다. 회로.

1

2

3

4

5

6

7

8

9

class Block {

  constructor(index, previousHash, timestamp, data, hash) {

    this.index = index;

    this.previousHash = previousHash.toString();

    this.timestamp = timestamp;

    this.data = data;

    this.hash = hash.toString();

  }

}

로그인 후 복사

해시 단위

해시 블록은 데이터의 무결성을 유지하는 데 필요합니다. 우리의 경우 이는 SHA-256 알고리즘에 적용됩니다. 이러한 유형의 해싱은 마이닝과 관련이 없습니다. 이 경우 성능 증명을 통한 보호를 구현하지 않기 때문입니다.

1

2

3

var calculateHash = (index, previousHash, timestamp, data) => {

  return CryptoJS.SHA256(index + previousHash + timestamp + data).toString();

};

로그인 후 복사

세대 단위

블록을 생성하려면 이전 블록의 해시를 알아야 구조의 나머지 요소가 이미 결정되어 있습니다. 데이터는 최종 사용자가 제공합니다.

1

2

3

4

5

6

7

var generateNextBlock = (blockData) => {

  var previousBlock = getLatestBlock();

  var nextIndex = previousBlock.index + 1;

  var nextTimestamp = new Date().getTime() / 1000;

  var nextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData);

  return new Block(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);

};

로그인 후 복사

저장 장치

블록체인 저장소 어레이를 사용하세요. 첫 번째 블록은 항상 "Genesis Block"으로 하드코딩됩니다.

1

2

3

4

var getGenesisBlock = () => {

  return new Block(0, "0", 1465154705, "my genesis block!!", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7");

};

var blockchain = [getGenesisBlock()];

로그인 후 복사

블록 무결성 확인

우리는 항상 장치나 회로의 무결성을 확인할 수 있어야 합니다. 특히 다른 유닛으로부터 새로운 유닛을 얻을 때, 이를 받아들일지 말지 결정해야 합니다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

var isValidNewBlock = (newBlock, previousBlock) => {

  if (previousBlock.index + 1 !== newBlock.index) {

    console.log('invalid index');

    return false;

  } else if (previousBlock.hash !== newBlock.previousHash) {

    console.log('invalid previoushash');

    return false;

  } else if (calculateHashForBlock(newBlock) !== newBlock.hash) {

    console.log(typeof (newBlock.hash) + ' ' + typeof calculateHashForBlock(newBlock));

    console.log('invalid hash: ' + calculateHashForBlock(newBlock) + ' ' + newBlock.hash);

    return false;

  }

  return true;

};

로그인 후 복사

가장 긴 체인을 선택하세요

회로의 블록 순서는 명시적으로 지정되어야 하지만 충돌이 발생하는 경우(예: 동일한 생성된 노드에서 동시에 두 개의 노드) 블록과 동일한 번호), 더 많은 수의 블록을 포함하는 회로를 선택합니다.

1

2

3

4

5

6

7

8

9

var replaceChain = (newBlocks) => {

  if (isValidChain(newBlocks) && newBlocks.length > blockchain.length) {

    console.log('Received blockchain is valid. Replacing current blockchain with received blockchain');

    blockchain = newBlocks;

    broadcast(responseLatestMsg());

  } else {

    console.log('Received blockchain invalid');

  }

};

로그인 후 복사

다른 네트워크 노드에 보내는 메시지

웹사이트의 필수 부분 - 다른 노드와의 데이터 교환. 네트워크 동기화를 유지하는 데는 다음 규칙이 사용됩니다.
노드가 새 유닛을 생성하면 이를 네트워크에 보고합니다.
로컬 머신이 새 잔치에 연결되면 마지막으로 생성된 블록에 대한 정보를 요청합니다. 더 큰 표시기가 있는 A 블록을 향하고 있으며 회로 또는 요청의 전체 정보 체인에 블록을 추가합니다.
동료 자동 검색은 수행되지 않으며 모든 링크는 수동으로 추가됩니다.

Control of Units

사용자는 HTTP 서버를 솔루션에 배치하여 어떤 방식으로든 노드를 제어할 수 있어야 합니다. 노드와 상호 작용할 때 다음 기능이 있습니다.

모든 유닛 목록 인쇄
사용자 생성 콘텐츠로 새 유닛 생성
목록 인쇄 또는 축제 추가.
상호작용하는 가장 직접적인 방법 - 컬을 통해:

노드의 모든 블록 목록 #

curl http://localhost:3001/blocks

Architecture

웹사이트가 주목할 가치가 있습니다. 두 개의 웹 서버를 의미합니다. 사용자 제어 설치를 위한 HTTP와 노드 간 P2P 연결 설치를 위한 WebSocket HTTP입니다.

다음은 200줄의 js 코드입니다

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

<span style="font-family:Arial, Helvetica, sans-serif;">'use strict';</span>

var CryptoJS = require("crypto-js");

var express = require("express");

var bodyParser = require('body-parser');

var WebSocket = require("ws");

var http_port = process.env.HTTP_PORT || 3001;

var p2p_port = process.env.P2P_PORT || 6001;

var initialPeers = process.env.PEERS ? process.env.PEERS.split(',') : [];

class Block {

  constructor(index, previousHash, timestamp, data, hash) {

    this.index = index;

    this.previousHash = previousHash.toString();

    this.timestamp = timestamp;

    this.data = data;

    this.hash = hash.toString();

  }

}

var sockets = [];

var MessageType = {

  QUERY_LATEST: 0,

  QUERY_ALL: 1,

  RESPONSE_BLOCKCHAIN: 2

};

var getGenesisBlock = () => {

  return new Block(0, "0", 1465154705, "my genesis block!!", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7");

};

var blockchain = [getGenesisBlock()];

var initHttpServer = () => {

  var app = express();

  app.use(bodyParser.json());

  app.get('/blocks', (req, res) => res.send(JSON.stringify(blockchain)));

  app.post('/mineBlock', (req, res) => {

    var newBlock = generateNextBlock(req.body.data);

    addBlock(newBlock);

    broadcast(responseLatestMsg());

    console.log('block added: ' + JSON.stringify(newBlock));

    res.send();

  });

  app.get('/peers', (req, res) => {

    res.send(sockets.map(s => s._socket.remoteAddress + ':' + s._socket.remotePort));

  });

  app.post('/addPeer', (req, res) => {

    connectToPeers([req.body.peer]);

    res.send();

  });

  app.listen(http_port, () => console.log('Listening http on port: ' + http_port));

};

var initP2PServer = () => {

  var server = new WebSocket.Server({port: p2p_port});

  server.on('connection', ws => initConnection(ws));

  console.log('listening websocket p2p port on: ' + p2p_port);

};

var initConnection = (ws) => {

  sockets.push(ws);

  initMessageHandler(ws);

  initErrorHandler(ws);

  write(ws, queryChainLengthMsg());

};

var initMessageHandler = (ws) => {

  ws.on('message', (data) => {

    var message = JSON.parse(data);

    console.log('Received message' + JSON.stringify(message));

    switch (message.type) {

      case MessageType.QUERY_LATEST:

        write(ws, responseLatestMsg());

        break;

      case MessageType.QUERY_ALL:

        write(ws, responseChainMsg());

        break;

      case MessageType.RESPONSE_BLOCKCHAIN:

        handleBlockchainResponse(message);

        break;

    }

  });

};

var initErrorHandler = (ws) => {

  var closeConnection = (ws) => {

    console.log('connection failed to peer: ' + ws.url);

    sockets.splice(sockets.indexOf(ws), 1);

  };

  ws.on('close', () => closeConnection(ws));

  ws.on('error', () => closeConnection(ws));

};

var generateNextBlock = (blockData) => {

  var previousBlock = getLatestBlock();

  var nextIndex = previousBlock.index + 1;

  var nextTimestamp = new Date().getTime() / 1000;

  var nextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData);

  return new Block(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);

};

var calculateHashForBlock = (block) => {

  return calculateHash(block.index, block.previousHash, block.timestamp, block.data);

};

var calculateHash = (index, previousHash, timestamp, data) => {

  return CryptoJS.SHA256(index + previousHash + timestamp + data).toString();

};

var addBlock = (newBlock) => {

  if (isValidNewBlock(newBlock, getLatestBlock())) {

    blockchain.push(newBlock);

  }

};

var isValidNewBlock = (newBlock, previousBlock) => {

  if (previousBlock.index + 1 !== newBlock.index) {

    console.log(&#39;invalid index&#39;);

    return false;

  } else if (previousBlock.hash !== newBlock.previousHash) {

    console.log(&#39;invalid previoushash&#39;);

    return false;

  } else if (calculateHashForBlock(newBlock) !== newBlock.hash) {

    console.log(typeof (newBlock.hash) + &#39; &#39; + typeof calculateHashForBlock(newBlock));

    console.log(&#39;invalid hash: &#39; + calculateHashForBlock(newBlock) + &#39; &#39; + newBlock.hash);

    return false;

  }

  return true;

};

var connectToPeers = (newPeers) => {

  newPeers.forEach((peer) => {

    var ws = new WebSocket(peer);

    ws.on('open', () => initConnection(ws));

    ws.on('error', () => {

      console.log('connection failed')

    });

  });

};

var handleBlockchainResponse = (message) => {

  var receivedBlocks = JSON.parse(message.data).sort((b1, b2) => (b1.index - b2.index));

  var latestBlockReceived = receivedBlocks[receivedBlocks.length - 1];

  var latestBlockHeld = getLatestBlock();

  if (latestBlockReceived.index > latestBlockHeld.index) {

    console.log('blockchain possibly behind. We got: ' + latestBlockHeld.index + ' Peer got: ' + latestBlockReceived.index);

    if (latestBlockHeld.hash === latestBlockReceived.previousHash) {

      console.log("We can append the received block to our chain");

      blockchain.push(latestBlockReceived);

      broadcast(responseLatestMsg());

    } else if (receivedBlocks.length === 1) {

      console.log("We have to query the chain from our peer");

      broadcast(queryAllMsg());

    } else {

      console.log("Received blockchain is longer than current blockchain");

      replaceChain(receivedBlocks);

    }

  } else {

    console.log('received blockchain is not longer than received blockchain. Do nothing');

  }

};

var replaceChain = (newBlocks) => {

  if (isValidChain(newBlocks) && newBlocks.length > blockchain.length) {

    console.log(&#39;Received blockchain is valid. Replacing current blockchain with received blockchain&#39;);

    blockchain = newBlocks;

    broadcast(responseLatestMsg());

  } else {

    console.log(&#39;Received blockchain invalid&#39;);

  }

};

var isValidChain = (blockchainToValidate) => {

  if (JSON.stringify(blockchainToValidate[0]) !== JSON.stringify(getGenesisBlock())) {

    return false;

  }

  var tempBlocks = [blockchainToValidate[0]];

  for (var i = 1; i < blockchainToValidate.length; i++) {

    if (isValidNewBlock(blockchainToValidate[i], tempBlocks[i - 1])) {

      tempBlocks.push(blockchainToValidate[i]);

    } else {

      return false;

    }

  }

  return true;

};

var getLatestBlock = () => blockchain[blockchain.length - 1];

var queryChainLengthMsg = () => ({'type': MessageType.QUERY_LATEST});

var queryAllMsg = () => ({'type': MessageType.QUERY_ALL});

var responseChainMsg = () =>({

  'type': MessageType.RESPONSE_BLOCKCHAIN, 'data': JSON.stringify(blockchain)

});

var responseLatestMsg = () => ({

  'type': MessageType.RESPONSE_BLOCKCHAIN,

  'data': JSON.stringify([getLatestBlock()])

});

var write = (ws, message) => ws.send(JSON.stringify(message));

var broadcast = (message) => sockets.forEach(socket => write(socket, message));

connectToPeers(initialPeers);

initHttpServer();

initP2PServer();

로그인 후 복사

위 내용은 제가 모두를 위해 정리한 내용입니다. 앞으로 모든 분들께 도움이 되기를 바랍니다.

관련 글:

NodeJS 상위 프로세스와 하위 프로세스 간 리소스 공유 원칙 및 구현 방법

Vue의 휴대폰 번호, 이메일 정기 인증 및 60년대 인증 코드 전송 예시

Vue가 구현한 것 활성 클릭 전환 방법

위 내용은 블록체인 구현을 위한 200줄의 코드 블록체인 예시에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. 크로스 플레이가 있습니까?
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Stead: 동남아시아의 해상 인프라에 대한 분산형 자금 조달을 가능하게 하는 혁신적인 RWA 프로젝트 Stead: 동남아시아의 해상 인프라에 대한 분산형 자금 조달을 가능하게 하는 혁신적인 RWA 프로젝트 Aug 08, 2024 am 06:46 AM

Stead는 동남아시아에 기반을 둔 RWA 프로젝트입니다. 낚시 및 운송 보트, 물고기 우리, 수상 가옥을 포함한 해상 인프라를 위한 분산형 자금 조달 플랫폼 역할을 합니다.

VUE3 시작하기 예: 간단한 비디오 플레이어 만들기 VUE3 시작하기 예: 간단한 비디오 플레이어 만들기 Jun 15, 2023 pm 09:42 PM

새로운 세대의 프런트엔드 프레임워크가 계속 등장함에 따라 VUE3는 빠르고 유연하며 사용하기 쉬운 프런트엔드 프레임워크로 사랑받고 있습니다. 다음으로 VUE3의 기본을 배우고 간단한 동영상 플레이어를 만들어 보겠습니다. 1. VUE3 설치 먼저 VUE3를 로컬에 설치해야 합니다. 명령줄 도구를 열고 다음 명령을 실행합니다. npminstallvue@next 그런 다음 새 HTML 파일을 만들고 VUE3을 도입합니다. &lt;!doctypehtml&gt;

Golang의 포인터 변환 모범 사례를 알아보세요. Golang의 포인터 변환 모범 사례를 알아보세요. Feb 24, 2024 pm 03:51 PM

Golang은 다양한 애플리케이션과 서비스를 개발하는 데 사용할 수 있는 강력하고 효율적인 프로그래밍 언어입니다. Golang에서 포인터는 데이터를 보다 유연하고 효율적으로 운영하는 데 도움이 되는 매우 중요한 개념입니다. 포인터 변환은 다양한 유형 간의 포인터 작업 프로세스를 나타냅니다. 이 기사에서는 특정 예제를 사용하여 Golang의 포인터 변환 모범 사례를 학습합니다. 1. 기본 개념 Golang에서 각 변수에는 주소가 있으며, 주소는 메모리에서 변수의 위치입니다.

Oracle 인스턴스 수와 데이터베이스 성능 간의 관계 Oracle 인스턴스 수와 데이터베이스 성능 간의 관계 Mar 08, 2024 am 09:27 AM

Oracle 인스턴스 수와 데이터베이스 성능 간의 관계 Oracle 데이터베이스는 업계에서 잘 알려진 관계형 데이터베이스 관리 시스템 중 하나이며 엔터프라이즈 수준의 데이터 저장 및 관리에 널리 사용됩니다. Oracle 데이터베이스에서 인스턴스는 매우 중요한 개념입니다. 인스턴스는 메모리 내 Oracle 데이터베이스가 실행되는 환경을 의미합니다. 각 인스턴스는 사용자 요청을 처리하고 데이터베이스 작업을 관리하는 데 사용되는 독립적인 메모리 구조와 백그라운드 프로세스를 갖습니다. 인스턴스 수는 Oracle 데이터베이스의 성능과 안정성에 중요한 영향을 미칩니다.

PHP 간단한 웹 크롤러 개발 예제 PHP 간단한 웹 크롤러 개발 예제 Jun 13, 2023 pm 06:54 PM

인터넷의 급속한 발전으로 인해 데이터는 오늘날 정보화 시대의 가장 중요한 자원 중 하나가 되었습니다. 웹 크롤러는 네트워크 데이터를 자동으로 획득하고 처리하는 기술로 점점 더 많은 관심과 활용을 불러일으키고 있습니다. 이 기사에서는 PHP를 사용하여 간단한 웹 크롤러를 개발하고 네트워크 데이터를 자동으로 가져오는 기능을 구현하는 방법을 소개합니다. 1. 웹 크롤러 개요 웹 크롤러는 네트워크 자원을 자동으로 획득하고 처리하는 기술로, 주요 작업 프로세스는 브라우저 동작을 시뮬레이션하고 지정된 URL 주소에 자동으로 액세스하여 모든 정보를 추출하는 것입니다.

Gin 프레임워크의 인증 코드 사용 예 Gin 프레임워크의 인증 코드 사용 예 Jun 23, 2023 am 08:10 AM

인터넷의 대중화로 인해 인증 코드는 로그인, 등록, 비밀번호 검색 및 기타 작업에 필요한 프로세스가 되었습니다. Gin 프레임워크에서는 인증 코드 기능 구현이 매우 간단해졌습니다. 이 기사에서는 타사 라이브러리를 사용하여 Gin 프레임워크에서 확인 코드 기능을 구현하는 방법을 소개하고 독자가 참조할 수 있는 샘플 코드를 제공합니다. 1. 종속 라이브러리 설치 인증 코드를 사용하기 전에 타사 라이브러리인 goCaptcha를 설치해야 합니다. goCaptcha를 설치하려면 goget 명령을 사용할 수 있습니다: $goget-ugithub

Django 프레임워크를 빠르게 시작하세요: 자세한 튜토리얼과 예제 Django 프레임워크를 빠르게 시작하세요: 자세한 튜토리얼과 예제 Sep 28, 2023 pm 03:05 PM

Django 프레임워크로 빠르게 시작하기: 자세한 튜토리얼 및 예제 소개: Django는 MTV(Model-Template-View) 아키텍처를 기반으로 하는 효율적이고 유연한 Python 웹 개발 프레임워크입니다. 간단하고 명확한 구문과 강력한 기능을 갖추고 있어 개발자가 안정적이고 유지 관리가 쉬운 웹 애플리케이션을 신속하게 구축하는 데 도움이 됩니다. 이 기사에서는 Django의 사용법을 자세히 소개하고 독자가 Django 프레임워크를 빠르게 시작할 수 있도록 구체적인 예제와 코드 샘플을 제공합니다. 1. D를 설치한다

Oracle 데이터베이스의 인스턴스 개요 Oracle 데이터베이스의 인스턴스 개요 Mar 07, 2024 pm 04:42 PM

Oracle 데이터베이스는 강력한 기능과 유연성을 제공하는 세계 최고의 관계형 데이터베이스 관리 시스템 중 하나이며 엔터프라이즈 수준 시스템에서 널리 사용됩니다. Oracle 데이터베이스에서 인스턴스는 데이터베이스의 실행 환경과 메모리 구조를 담당하며 사용자와 연결하고 SQL 작업을 수행하는 데 있어 매우 중요한 개념입니다. Oracle 데이터베이스 인스턴스란 무엇입니까? Oracle 데이터베이스 인스턴스는 데이터베이스 인스턴스의 메모리 구조 및 백그라운드 프로세스를 포함하여 데이터베이스가 시작될 때 생성되는 프로세스의 모음입니다. 예시와

See all articles