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: 1263

  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. ​
  6. 3
  7. def __init__():
  8. 4
  9. ​
  10. 5
  11. pass
  12. 6
  13. ​
  14. 7
  15. #initial structure of the block class
  16. 8
  17. ​
  18. 9
  19. def compute_hash():
  20. 10
  21. ​
  22. 11
  23. pass
  24. 12
  25. ​
  26. 13
  27. #producing the cryptographic hash of each block
  28. 14
  29. ​
  30. 15
  31. class BlockChain(object):
  32. 16
  33. ​
  34. 17
  35. def __init__(self):
  36. 18
  37. ​
  38. 19
  39. #building the chain
  40. 20
  41. ​
  42. 21
  43. def build_genesis(self):
  44. 22
  45. ​
  46. 23
  47. pass
  48. 24
  49. ​
  50. 25
  51. #creating the initial block
  52. 26
  53. ​
  54. 27
  55. def build_block(self, proof_number, previous_hash):
  56. 28
  57. ​
  58. 29
  59. pass
  60. 30
  61. ​
  62. 31
  63. #builds new block and adds to the chain
  64. 32
  65. ​
  66. 33
  67. @staticmethod
  68. 34
  69. ​
  70. 35
  71. def confirm_validity(block, previous_block):
  72. 36
  73. ​
  74. 37
  75. pass
  76. 38
  77. ​
  78. 39
  79. #checks whether the blockchain is valid
  80. 40
  81. ​
  82. 41
  83. def get_data(self, sender, receiver, amount):
  84. 42
  85. ​
  86. 43
  87. pass
  88. 44
  89. ​
  90. 45
  91. # declares data of transactions
  92. 46
  93. ​
  94. 47
  95. @staticmethod
  96. 48
  97. ​
  98. 49
  99. def proof_of_work(last_proof):
  100. 50
  101. ​
  102. 51
  103. pass
  104. 52
  105. ​
  106. 53
  107. #adds to the security of the blockchain
  108. 54
  109. ​
  110. 55
  111. @property
  112. 56
  113. ​
  114. 57
  115. def latest_block(self):
  116. 58
  117. ​
  118. 59
  119. pass
  120. 60
  121. ​
  122. 61
  123. #returns the last block in the chain
  124. Now, let’s explain how the blockchain class works.
  125. Initial Structure of the Block Class
  126. Here is the code for our initial block class:
  127. 1
  128. import hashlib
  129. 2
  130. ​
  131. 3
  132. import time
  133. 4
  134. ​
  135. 5
  136. class Block(object):
  137. 6
  138. ​
  139. 7
  140. def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
  141. 8
  142. ​
  143. 9
  144. self.index = index
  145. 10
  146. ​
  147. 11
  148. self.proof_number = proof_number
  149. 12
  150. ​
  151. 13
  152. self.previous_hash = previous_hash
  153. 14
  154. ​
  155. 15
  156. self.data = data
  157. 16
  158. ​
  159. 17
  160. self.timestamp = timestamp or time.time()
  161. 18
  162. ​
  163. 19
  164. @property
  165. 20
  166. ​
  167. 21
  168. def compute_hash(self):
  169. 22
  170. ​
  171. 23
  172. string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
  173. 24
  174. ​
  175. 25
  176. return hashlib.sha256(string_block.encode()).hexdigest()
  177. As you can see above, the class constructor or initiation method ( __init__()) above takes the following parameters:
  178. 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.
  179. index — it’s used to track the position of a block within the blockchain.
  180. previous_hash — it used to reference the hash of the previous block within the blockchain.
  181. data—it gives details of the transactions done, for example, the amount bought.
  182. timestamp—it inserts a timestamp for all the transactions performed.
  183. The second method in the class, compute_hash , is used to produce the cryptographic hash of each block based on the above values.
  184. As you can see, we imported the SHA-256 algorithm into the cryptocurrency blockchain project to help in getting the hashes of the blocks.
  185. Once the values have been placed inside the hashing module, the algorithm will return a 256-bit string denoting the contents of the block.
  186. 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.
  187. Building the Chain
  188. 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.
  189. It will keep the transactions data and include other helper methods for completing various roles, such as adding new blocks.
  190. Let’s talk about the helper methods.
  191. Adding the Constructor Method
  192. Here is the code:
  193. 1
  194. class BlockChain(object):
  195. 2
  196. ​
  197. 3
  198. def __init__(self):
  199. 4
  200. ​
  201. 5
  202. self.chain = []
  203. 6
  204. ​
  205. 7
  206. self.current_data = []
  207. 8
  208. ​
  209. 9
  210. self.nodes = set()
  211. 10
  212. ​
  213. 11
  214. self.build_genesis()
  215. The __init__() constructor method is what instantiates the blockchain.
  216. Here are the roles of its attributes:
  217. self.chain — this variable stores all the blocks.
  218. self.current_data — this variable stores information about the transactions in the block.
  219. self.build_genesis() — this method is used to create the initial block in the chain.
  220. Building the Genesis Block
  221. 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.
  222. 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.
  223. Here is the code:
  224. 1
  225. def build_genesis(self):
  226. 2
  227. ​
  228. 3
  229. self.build_block(proof_number=0, previous_hash=0)
  230. 4
  231. ​
  232. 5
  233. def build_block(self, proof_number, previous_hash):
  234. 6
  235. ​
  236. 7
  237. block = Block(
  238. 8
  239. ​
  240. 9
  241. index=len(self.chain),
  242. 10
  243. ​
  244. 11
  245. proof_number=proof_number,
  246. 12
  247. ​
  248. 13
  249. previous_hash=previous_hash,
  250. 14
  251. ​
  252. 15
  253. data=self.current_data
  254. 16
  255. ​
  256. 17
  257. )
  258. 18
  259. ​
  260. 19
  261. self.current_data = []
  262. 20
  263. ​
  264. 21
  265. self.chain.append(block)
  266. 22
  267. ​
  268. 23
  269. return block
  270. Confirming Validity of the Blockchain
  271. The confirm_validity method is critical in examining the integrity of the blockchain and making sure inconsistencies are lacking.
  272. 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.
  273. Thus, the confirm_validity method utilizes a series of if statements to assess whether the hash of each block has been compromised.
  274. 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.
  275. Here is the code:
  276. 1
  277. def confirm_validity(block, previous_block):
  278. 2
  279. ​
  280. 3
  281. if previous_block.index + 1 != block.index:
  282. 4
  283. ​
  284. 5
  285. return False
  286. 6
  287. ​
  288. 7
  289. elif previous_block.compute_hash != block.previous_hash:
  290. 8
  291. ​
  292. 9
  293. return False
  294. 10
  295. ​
  296. 11
  297. elif block.timestamp <= previous_block.timestamp:
  298. 12
  299. ​
  300. 13
  301. return False
  302. 14
  303. ​
  304. 15
  305. return True
  306. Declaring Data of Transactions
  307. 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.
  308. Here is the code:
  309. 1
  310. def get_data(self, sender, receiver, amount):
  311. 2
  312. ​
  313. 3
  314. self.current_data.append({
  315. 4
  316. ​
  317. 5
  318. 'sender': sender,
  319. 6
  320. ​
  321. 7
  322. 'receiver': receiver,
  323. 8
  324. ​
  325. 9
  326. 'amount': amount
  327. 10
  328. ​
  329. 11
  330. })
  331. 12
  332. ​
  333. 13
  334. return True
  335. Effecting the Proof of Work
  336. In blockchain technology, Proof of Work (PoW) refers to the complexity involved in mining or generating new blocks on the blockchain.
  337. 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.
  338. This way, it discourages spamming and compromising the integrity of the network.
  339. In this article, we’ll illustrate how to include a Proof of Work algorithm in a blockchain cryptocurrency project.
  340. Finalizing With the Last Block
  341. Finally, the latest_block() helper method is used for retrieving the last block on the network, which is actually the current block.
  342. Here is the code:
  343. 1
  344. def latest_block(self):
  345. 2
  346. ​
  347. 3
  348. return self.chain[-1]
  349. Implementing Blockchain Mining
  350. Now, this is the most exciting section!
  351. 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.
  352. 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.
  353. Here is the mining method in this simple cryptocurrency blockchain project:
  354. 1
  355. def block_mining(self, details_miner):
  356. 2
  357. ​
  358. 3
  359. self.get_data(
  360. 4
  361. ​
  362. 5
  363. sender="0", #it implies that this node has created a new block
  364. 6
  365. ​
  366. 7
  367. receiver=details_miner,
  368. 8
  369. ​
  370. 9
  371. quantity=1, #creating a new block (or identifying the proof number) is awarded with 1
  372. 10
  373. ​
  374. 11
  375. )
  376. 12
  377. ​
  378. 13
  379. last_block = self.latest_block
  380. 14
  381. ​
  382. 15
  383. last_proof_number = last_block.proof_number
  384. 16
  385. ​
  386. 17
  387. proof_number = self.proof_of_work(last_proof_number)
  388. 18
  389. ​
  390. 19
  391. ​
  392. 20
  393. ​
  394. 21
  395. last_hash = last_block.compute_hash
  396. 22
  397. ​
  398. 23
  399. block = self.build_block(proof_number, last_hash)
  400. 24
  401. ​
  402. 25
  403. ​
  404. 26
  405. ​
  406. 27
  407. return vars(block)
  408. 28
  409. ​
  410. 29
  411. ​
  412. Summary
  413. Here is the whole code for our crypto blockchain class in Python:
  414. 1
  415. import hashlib
  416. 2
  417. ​
  418. 3
  419. import time
  420. 4
  421. ​
  422. 5
  423. class Block(object):
  424. 6
  425. ​
  426. 7
  427. def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
  428. 8
  429. ​
  430. 9
  431. self.index = index
  432. 10
  433. ​
  434. 11
  435. self.proof_number = proof_number
  436. 12
  437. ​
  438. 13
  439. self.previous_hash = previous_hash
  440. 14
  441. ​
  442. 15
  443. self.data = data
  444. 16
  445. ​
  446. 17
  447. self.timestamp = timestamp or time.time()
  448. 18
  449. ​
  450. 19
  451. @property
  452. 20
  453. ​
  454. 21
  455. def compute_hash(self):
  456. 22
  457. ​
  458. 23
  459. string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
  460. 24
  461. ​
  462. 25
  463. return hashlib.sha256(string_block.encode()).hexdigest()
  464. 26
  465. ​
  466. 27
  467. def __repr__(self):
  468. 28
  469. ​
  470. 29
  471. return "{} - {} - {} - {} - {}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
  472. 30
  473. ​
  474. 31
  475. class BlockChain(object):
  476. 32
  477. ​
  478. 33
  479. def __init__(self):
  480. 34
  481. ​
  482. 35
  483. self.chain = []
  484. 36
  485. ​
  486. 37
  487. self.current_data = []
  488. 38
  489. ​
  490. 39
  491. self.nodes = set()
  492. 40
  493. ​
  494. 41
  495. self.build_genesis()
  496. 42
  497. ​
  498. 43
  499. def build_genesis(self):
  500. 44
  501. ​
  502. 45
  503. self.build_block(proof_number=0, previous_hash=0)
  504. 46
  505. ​
  506. 47
  507. def build_block(self, proof_number, previous_hash):
  508. 48
  509. ​
  510. 49
  511. block = Block(
  512. 50
  513. ​
  514. 51
  515. index=len(self.chain),
  516. 52
  517. ​
  518. 53
  519. proof_number=proof_number,
  520. 54
  521. ​
  522. 55
  523. previous_hash=previous_hash,
  524. 56
  525. ​
  526. 57
  527. data=self.current_data
  528. 58
  529. ​
  530. 59
  531. )
  532. 60
  533. ​
  534. 61
  535. self.current_data = []
  536. 62
  537. ​
  538. 63
  539. self.chain.append(block)
  540. 64
  541. ​
  542. 65
  543. return block
  544. 66
  545. ​
  546. 67
  547. @staticmethod
  548. 68
  549. ​
  550. 69
  551. def confirm_validity(block, previous_block):
  552. 70
  553. ​
  554. 71
  555. if previous_block.index + 1 != block.index:
  556. 72
  557. ​
  558. 73
  559. return False
  560. 74
  561. ​
  562. 75
  563. elif previous_block.compute_hash != block.previous_hash:
  564. 76
  565. ​
  566. 77
  567. return False
  568. 78
  569. ​
  570. 79
  571. elif block.timestamp <= previous_block.timestamp:
  572. 80
  573. ​
  574. 81
  575. return False
  576. 82
  577. ​
  578. 83
  579. return True
  580. 84
  581. ​
  582. 85
  583. def get_data(self, sender, receiver, amount):
  584. 86
  585. ​
  586. 87
  587. self.current_data.append({
  588. 88
  589. ​
  590. 89
  591. 'sender': sender,
  592. 90
  593. ​
  594. 91
  595. 'receiver': receiver,
  596. 92
  597. ​
  598. 93
  599. 'amount': amount
  600. 94
  601. ​
  602. 95
  603. })
  604. 96
  605. ​
  606. 97
  607. return True
  608. 98
  609. ​
  610. 99
  611. @staticmethod
  612. 100
  613. ​
  614. 101
  615. def proof_of_work(last_proof):
  616. 102
  617. ​
  618. 103
  619. pass
  620. 104
  621. ​
  622. 105
  623. @property
  624. 106
  625. ​
  626. 107
  627. def latest_block(self):
  628. 108
  629. ​
  630. 109
  631. return self.chain[-1]
  632. 110
  633. ​
  634. 111
  635. def chain_validity(self):
  636. 112
  637. ​
  638. 113
  639. pass
  640. 114
  641. ​
  642. 115
  643. def block_mining(self, details_miner):
  644. 116
  645. ​
  646. 117
  647. self.get_data(
  648. 118
  649. ​
  650. 119
  651. sender="0", #it implies that this node has created a new block
  652. 120
  653. ​
  654. 121
  655. receiver=details_miner,
  656. 122
  657. ​
  658. 123
  659. quantity=1, #creating a new block (or identifying the proof number) is awared with 1
  660. 124
  661. ​
  662. 125
  663. )
  664. 126
  665. ​
  666. 127
  667. last_block = self.latest_block
  668. 128
  669. ​
  670. 129
  671. last_proof_number = last_block.proof_number
  672. 130
  673. ​
  674. 131
  675. proof_number = self.proof_of_work(last_proof_number)
  676. 132
  677. ​
  678. 133
  679. last_hash = last_block.compute_hash
  680. 134
  681. ​
  682. 135
  683. block = self.build_block(proof_number, last_hash)
  684. 136
  685. ​
  686. 137
  687. return vars(block)
  688. 138
  689. ​
  690. 139
  691. def create_node(self, address):
  692. 140
  693. ​
  694. 141
  695. self.nodes.add(address)
  696. 142
  697. ​
  698. 143
  699. return True
  700. 144
  701. ​
  702. 145
  703. @staticmethod
  704. 146
  705. ​
  706. 147
  707. def get_block_object(block_data):
  708. 148
  709. ​
  710. 149
  711. return Block(
  712. 150
  713. ​
  714. 151
  715. block_data['index'],
  716. 152
  717. ​
  718. 153
  719. block_data['proof_number'],
  720. 154
  721. ​
  722. 155
  723. block_data['previous_hash'],
  724. 156
  725. ​
  726. 157
  727. block_data['data'],
  728. 158
  729. ​
  730. 159
  731. timestamp=block_data['timestamp']
  732. 160
  733. ​
  734. 161
  735. )
  736. 162
  737. ​
  738. 163
  739. blockchain = BlockChain()
  740. 164
  741. ​
  742. 165
  743. print("GET READY MINING ABOUT TO START")
  744. 166
  745. ​
  746. 167
  747. print(blockchain.chain)
  748. 168
  749. ​
  750. 169
  751. last_block = blockchain.latest_block
  752. 170
  753. ​
  754. 171
  755. last_proof_number = last_block.proof_number
  756. 172
  757. ​
  758. 173
  759. proof_number = blockchain.proof_of_work(last_proof_number)
  760. 174
  761. ​
  762. 175
  763. blockchain.get_data(
  764. 176
  765. ​
  766. 177
  767. sender="0", #this means that this node has constructed another block
  768. 178
  769. ​
  770. 179
  771. receiver="LiveEdu.tv",
  772. 180
  773. ​
  774. 181
  775. amount=1, #building a new block (or figuring out the proof number) is awarded with 1
  776. 182
  777. ​
  778. 183
  779. )
  780. 184
  781. ​
  782. 185
  783. last_hash = last_block.compute_hash
  784. 186
  785. ​
  786. 187
  787. block = blockchain.build_block(proof_number, last_hash)
  788. 188
  789. ​
  790. 189
  791. print("WOW, MINING HAS BEEN SUCCESSFUL!")
  792. 190
  793. ​
  794. 191
  795. print(blockchain.chain)
  796. Now, let’s try to run our code to see if we can generate some digital coins...

comments powered by Disqus