How to create your own Crypto Blockchain.


SUBMITTED BY: godsend

DATE: Dec. 1, 2020, 4:54 p.m.

UPDATED: Feb. 12, 2021, 3:59 p.m.

FORMAT: Text only

SIZE: 14.4 kB

HITS: 998

  1. Here is the basic blueprint of the Python class we’ll use for creating the blockchain:
  2. 1
  3. class Block(object):
  4. 2
  5. 3
  6. def __init__():
  7. 4
  8. 5
  9. pass
  10. 6
  11. 7
  12. #initial structure of the block class
  13. 8
  14. 9
  15. def compute_hash():
  16. 10
  17. 11
  18. pass
  19. 12
  20. 13
  21. #producing the cryptographic hash of each block
  22. 14
  23. 15
  24. class BlockChain(object):
  25. 16
  26. 17
  27. def __init__(self):
  28. 18
  29. 19
  30. #building the chain
  31. 20
  32. 21
  33. def build_genesis(self):
  34. 22
  35. 23
  36. pass
  37. 24
  38. 25
  39. #creating the initial block
  40. 26
  41. 27
  42. def build_block(self, proof_number, previous_hash):
  43. 28
  44. 29
  45. pass
  46. 30
  47. 31
  48. #builds new block and adds to the chain
  49. 32
  50. 33
  51. @staticmethod
  52. 34
  53. 35
  54. def confirm_validity(block, previous_block):
  55. 36
  56. 37
  57. pass
  58. 38
  59. 39
  60. #checks whether the blockchain is valid
  61. 40
  62. 41
  63. def get_data(self, sender, receiver, amount):
  64. 42
  65. 43
  66. pass
  67. 44
  68. 45
  69. # declares data of transactions
  70. 46
  71. 47
  72. @staticmethod
  73. 48
  74. 49
  75. def proof_of_work(last_proof):
  76. 50
  77. 51
  78. pass
  79. 52
  80. 53
  81. #adds to the security of the blockchain
  82. 54
  83. 55
  84. @property
  85. 56
  86. 57
  87. def latest_block(self):
  88. 58
  89. 59
  90. pass
  91. 60
  92. 61
  93. #returns the last block in the chain
  94. Now, let’s explain how the blockchain class works.
  95. Initial Structure of the Block Class
  96. Here is the code for our initial block class:
  97. 1
  98. import hashlib
  99. 2
  100. 3
  101. import time
  102. 4
  103. 5
  104. class Block(object):
  105. 6
  106. 7
  107. def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
  108. 8
  109. 9
  110. self.index = index
  111. 10
  112. 11
  113. self.proof_number = proof_number
  114. 12
  115. 13
  116. self.previous_hash = previous_hash
  117. 14
  118. 15
  119. self.data = data
  120. 16
  121. 17
  122. self.timestamp = timestamp or time.time()
  123. 18
  124. 19
  125. @property
  126. 20
  127. 21
  128. def compute_hash(self):
  129. 22
  130. 23
  131. string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
  132. 24
  133. 25
  134. return hashlib.sha256(string_block.encode()).hexdigest()
  135. As you can see above, the class constructor or initiation method ( __init__()) above takes the following parameters:
  136. self — just like any other Python class, this parameter is used to refer to the class itself. Any variable associated with the class can be accessed using it.
  137. index — it’s used to track the position of a block within the blockchain.
  138. previous_hash — it used to reference the hash of the previous block within the blockchain.
  139. data—it gives details of the transactions done, for example, the amount bought.
  140. timestamp—it inserts a timestamp for all the transactions performed.
  141. The second method in the class, compute_hash , is used to produce the cryptographic hash of each block based on the above values.
  142. As you can see, we imported the SHA-256 algorithm into the cryptocurrency blockchain project to help in getting the hashes of the blocks.
  143. Once the values have been placed inside the hashing module, the algorithm will return a 256-bit string denoting the contents of the block.
  144. So, this is what gives the blockchain immutability. Since each block will be represented by a hash, which will be computed from the hash of the previous block, corrupting any block in the chain will make the other blocks have invalid hashes, resulting in breakage of the whole blockchain network.
  145. Building the Chain
  146. The whole concept of a blockchain is based on the fact that the blocks are “chained” to each other. Now, we’ll create a blockchain class that will play the critical role of managing the entire chain.
  147. It will keep the transactions data and include other helper methods for completing various roles, such as adding new blocks.
  148. Let’s talk about the helper methods.
  149. Adding the Constructor Method
  150. Here is the code:
  151. 1
  152. class BlockChain(object):
  153. 2
  154. 3
  155. def __init__(self):
  156. 4
  157. 5
  158. self.chain = []
  159. 6
  160. 7
  161. self.current_data = []
  162. 8
  163. 9
  164. self.nodes = set()
  165. 10
  166. 11
  167. self.build_genesis()
  168. The __init__() constructor method is what instantiates the blockchain.
  169. Here are the roles of its attributes:
  170. self.chain — this variable stores all the blocks.
  171. self.current_data — this variable stores information about the transactions in the block.
  172. self.build_genesis() — this method is used to create the initial block in the chain.
  173. Building the Genesis Block
  174. The build_genesis() method is used for creating the initial block in the chain, that is, a block without any predecessors. The genesis block is what represents the beginning of the blockchain.
  175. To create it, we’ll call the build_block() method and give it some default values. The parameters proof_number and previous_hash are both given a value of zero, though you can give them any value you desire.
  176. Here is the code:
  177. 1
  178. def build_genesis(self):
  179. 2
  180. 3
  181. self.build_block(proof_number=0, previous_hash=0)
  182. 4
  183. 5
  184. def build_block(self, proof_number, previous_hash):
  185. 6
  186. 7
  187. block = Block(
  188. 8
  189. 9
  190. index=len(self.chain),
  191. 10
  192. 11
  193. proof_number=proof_number,
  194. 12
  195. 13
  196. previous_hash=previous_hash,
  197. 14
  198. 15
  199. data=self.current_data
  200. 16
  201. 17
  202. )
  203. 18
  204. 19
  205. self.current_data = []
  206. 20
  207. 21
  208. self.chain.append(block)
  209. 22
  210. 23
  211. return block
  212. Confirming Validity of the Blockchain
  213. The confirm_validity method is critical in examining the integrity of the blockchain and making sure inconsistencies are lacking.
  214. As explained earlier, hashes are pivotal for realizing the security of the cryptocurrency blockchain, because any slight alteration in an object will result in the creation of an entirely different hash.
  215. Thus, the confirm_validity method utilizes a series of if statements to assess whether the hash of each block has been compromised.
  216. Furthermore, it also compares the hash values of every two successive blocks to identify any anomalies. If the chain is working properly, it returns true; otherwise, it returns false.
  217. Here is the code:
  218. 1
  219. def confirm_validity(block, previous_block):
  220. 2
  221. 3
  222. if previous_block.index + 1 != block.index:
  223. 4
  224. 5
  225. return False
  226. 6
  227. 7
  228. elif previous_block.compute_hash != block.previous_hash:
  229. 8
  230. 9
  231. return False
  232. 10
  233. 11
  234. elif block.timestamp <= previous_block.timestamp:
  235. 12
  236. 13
  237. return False
  238. 14
  239. 15
  240. return True
  241. Declaring Data of Transactions
  242. The get_data method is important in declaring the data of transactions on a block. This method takes three parameters (sender’s information, receiver’s information, and amount) and adds the transaction data to the self.current_data list.
  243. Here is the code:
  244. 1
  245. def get_data(self, sender, receiver, amount):
  246. 2
  247. 3
  248. self.current_data.append({
  249. 4
  250. 5
  251. 'sender': sender,
  252. 6
  253. 7
  254. 'receiver': receiver,
  255. 8
  256. 9
  257. 'amount': amount
  258. 10
  259. 11
  260. })
  261. 12
  262. 13
  263. return True
  264. Effecting the Proof of Work
  265. In blockchain technology, Proof of Work (PoW) refers to the complexity involved in mining or generating new blocks on the blockchain.
  266. For example, the PoW can be implemented by identifying a number that solves a problem whenever a user completes some computing work. Anyone on the blockchain network should find the number complex to identify but easy to verify — this is the main concept of PoW.
  267. This way, it discourages spamming and compromising the integrity of the network.
  268. In this article, we’ll illustrate how to include a Proof of Work algorithm in a blockchain cryptocurrency project.
  269. Finalizing With the Last Block
  270. Finally, the latest_block() helper method is used for retrieving the last block on the network, which is actually the current block.
  271. Here is the code:
  272. 1
  273. def latest_block(self):
  274. 2
  275. 3
  276. return self.chain[-1]
  277. Implementing Blockchain Mining
  278. Now, this is the most exciting section!
  279. Initially, the transactions are kept in a list of unverified transactions. Mining refers to the process of placing the unverified transactions in a block and solving the PoW problem. It can be referred to as the computing work involved in verifying the transactions.
  280. If everything has been figured out correctly, a block is created or mined and joined together with the others in the blockchain. If users have successfully mined a block, they are often rewarded for using their computing resources to solve the PoW problem.
  281. Here is the mining method in this simple cryptocurrency blockchain project:
  282. 1
  283. def block_mining(self, details_miner):
  284. 2
  285. 3
  286. self.get_data(
  287. 4
  288. 5
  289. sender="0", #it implies that this node has created a new block
  290. 6
  291. 7
  292. receiver=details_miner,
  293. 8
  294. 9
  295. quantity=1, #creating a new block (or identifying the proof number) is awarded with 1
  296. 10
  297. 11
  298. )
  299. 12
  300. 13
  301. last_block = self.latest_block
  302. 14
  303. 15
  304. last_proof_number = last_block.proof_number
  305. 16
  306. 17
  307. proof_number = self.proof_of_work(last_proof_number)
  308. 18
  309. 19
  310. 20
  311. 21
  312. last_hash = last_block.compute_hash
  313. 22
  314. 23
  315. block = self.build_block(proof_number, last_hash)
  316. 24
  317. 25
  318. 26
  319. 27
  320. return vars(block)
  321. 28
  322. 29
  323. Summary
  324. Here is the whole code for our crypto blockchain class in Python:
  325. 1
  326. import hashlib
  327. 2
  328. 3
  329. import time
  330. 4
  331. 5
  332. class Block(object):
  333. 6
  334. 7
  335. def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
  336. 8
  337. 9
  338. self.index = index
  339. 10
  340. 11
  341. self.proof_number = proof_number
  342. 12
  343. 13
  344. self.previous_hash = previous_hash
  345. 14
  346. 15
  347. self.data = data
  348. 16
  349. 17
  350. self.timestamp = timestamp or time.time()
  351. 18
  352. 19
  353. @property
  354. 20
  355. 21
  356. def compute_hash(self):
  357. 22
  358. 23
  359. string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
  360. 24
  361. 25
  362. return hashlib.sha256(string_block.encode()).hexdigest()
  363. 26
  364. 27
  365. def __repr__(self):
  366. 28
  367. 29
  368. return "{} - {} - {} - {} - {}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
  369. 30
  370. 31
  371. class BlockChain(object):
  372. 32
  373. 33
  374. def __init__(self):
  375. 34
  376. 35
  377. self.chain = []
  378. 36
  379. 37
  380. self.current_data = []
  381. 38
  382. 39
  383. self.nodes = set()
  384. 40
  385. 41
  386. self.build_genesis()
  387. 42
  388. 43
  389. def build_genesis(self):
  390. 44
  391. 45
  392. self.build_block(proof_number=0, previous_hash=0)
  393. 46
  394. 47
  395. def build_block(self, proof_number, previous_hash):
  396. 48
  397. 49
  398. block = Block(
  399. 50
  400. 51
  401. index=len(self.chain),
  402. 52
  403. 53
  404. proof_number=proof_number,
  405. 54
  406. 55
  407. previous_hash=previous_hash,
  408. 56
  409. 57
  410. data=self.current_data
  411. 58
  412. 59
  413. )
  414. 60
  415. 61
  416. self.current_data = []
  417. 62
  418. 63
  419. self.chain.append(block)
  420. 64
  421. 65
  422. return block
  423. 66
  424. 67
  425. @staticmethod
  426. 68
  427. 69
  428. def confirm_validity(block, previous_block):
  429. 70
  430. 71
  431. if previous_block.index + 1 != block.index:
  432. 72
  433. 73
  434. return False
  435. 74
  436. 75
  437. elif previous_block.compute_hash != block.previous_hash:
  438. 76
  439. 77
  440. return False
  441. 78
  442. 79
  443. elif block.timestamp <= previous_block.timestamp:
  444. 80
  445. 81
  446. return False
  447. 82
  448. 83
  449. return True
  450. 84
  451. 85
  452. def get_data(self, sender, receiver, amount):
  453. 86
  454. 87
  455. self.current_data.append({
  456. 88
  457. 89
  458. 'sender': sender,
  459. 90
  460. 91
  461. 'receiver': receiver,
  462. 92
  463. 93
  464. 'amount': amount
  465. 94
  466. 95
  467. })
  468. 96
  469. 97
  470. return True
  471. 98
  472. 99
  473. @staticmethod
  474. 100
  475. 101
  476. def proof_of_work(last_proof):
  477. 102
  478. 103
  479. pass
  480. 104
  481. 105
  482. @property
  483. 106
  484. 107
  485. def latest_block(self):
  486. 108
  487. 109
  488. return self.chain[-1]
  489. 110
  490. 111
  491. def chain_validity(self):
  492. 112
  493. 113
  494. pass
  495. 114
  496. 115
  497. def block_mining(self, details_miner):
  498. 116
  499. 117
  500. self.get_data(
  501. 118
  502. 119
  503. sender="0", #it implies that this node has created a new block
  504. 120
  505. 121
  506. receiver=details_miner,
  507. 122
  508. 123
  509. quantity=1, #creating a new block (or identifying the proof number) is awared with 1
  510. 124
  511. 125
  512. )
  513. 126
  514. 127
  515. last_block = self.latest_block
  516. 128
  517. 129
  518. last_proof_number = last_block.proof_number
  519. 130
  520. 131
  521. proof_number = self.proof_of_work(last_proof_number)
  522. 132
  523. 133
  524. last_hash = last_block.compute_hash
  525. 134
  526. 135
  527. block = self.build_block(proof_number, last_hash)
  528. 136
  529. 137
  530. return vars(block)
  531. 138
  532. 139
  533. def create_node(self, address):
  534. 140
  535. 141
  536. self.nodes.add(address)
  537. 142
  538. 143
  539. return True
  540. 144
  541. 145
  542. @staticmethod
  543. 146
  544. 147
  545. def get_block_object(block_data):
  546. 148
  547. 149
  548. return Block(
  549. 150
  550. 151
  551. block_data['index'],
  552. 152
  553. 153
  554. block_data['proof_number'],
  555. 154
  556. 155
  557. block_data['previous_hash'],
  558. 156
  559. 157
  560. block_data['data'],
  561. 158
  562. 159
  563. timestamp=block_data['timestamp']
  564. 160
  565. 161
  566. )
  567. 162
  568. 163
  569. blockchain = BlockChain()
  570. 164
  571. 165
  572. print("GET READY MINING ABOUT TO START")
  573. 166
  574. 167
  575. print(blockchain.chain)
  576. 168
  577. 169
  578. last_block = blockchain.latest_block
  579. 170
  580. 171
  581. last_proof_number = last_block.proof_number
  582. 172
  583. 173
  584. proof_number = blockchain.proof_of_work(last_proof_number)
  585. 174
  586. 175
  587. blockchain.get_data(
  588. 176
  589. 177
  590. sender="0", #this means that this node has constructed another block
  591. 178
  592. 179
  593. receiver="LiveEdu.tv",
  594. 180
  595. 181
  596. amount=1, #building a new block (or figuring out the proof number) is awarded with 1
  597. 182
  598. 183
  599. )
  600. 184
  601. 185
  602. last_hash = last_block.compute_hash
  603. 186
  604. 187
  605. block = blockchain.build_block(proof_number, last_hash)
  606. 188
  607. 189
  608. print("WOW, MINING HAS BEEN SUCCESSFUL!")
  609. 190
  610. 191
  611. print(blockchain.chain)
  612. Now, let’s try to run our code to see if we can generate some digital coins...

comments powered by Disqus