In this article, we are going to implement a simple and plain “smart blockchain” with Python language and compare it with a blockchain. We hope that by doing this, the main concepts and advantages of this technology will be more clearly specified and welcomed by the developers and the blockchain community. A Block Producer Smart Contract (BPSC) exists in a plain “smart blockchain” network. To make a successful transaction in the network, the sender must first transfer the cryptocurrency to the (BPSC) wallet, and immediately the (BPSC) will automatically send the same cryptocurrency to the final recipient’s wallet. This seemingly simple task saves accurate and impervious data from all successful transactions in the (BPSC) Smart Contract. The present article was written in April 2020 by and in two versions in English and Persian. Somayyeh Gholami Mehran Kazeminia Persian Article Before you start, consider the following points: If you are unfamiliar with “smart blockchain” and have not read our previous articles on this technology, you can see the outline of the subject in the following article. However, the necessary explanations are given during the implementation We assume that the reader is familiar with the Python language and comprehend blockchain concepts, hash, and so on. For this reason and to avoid getting the story long and tedious, we’re focusing on “smart blockchain” features. Of course, if you forgot some of the concepts of blockchain, you can refer to the following article. In this article, the author has fully implemented a blockchain with Python. We also use his ideas and codes to implement “smart blockchain” so that we can easily compare “smart blockchain” with blockchain. Our Python version is Python 3.7 and we use Spyder-Anaconda3 as the IDE. You can use your favorite IDE like PyCharm and so on. Of course, for example, Jupyter Notebook is not suitable for this purpose. We will also use Postman, but you can also use cURL https://hackernoon.com/what-is-smart-blockchain-4b134275e90f https://hackernoon.com/learn-blockchains-by-building-one-117428612f46 Understand the functionality of “smart blockchain” through coding. Let’s get started and create a class called Smart_Blockchain. The constructor method of this class currently creates two empty lists, one for storing transactions and the other for storing chain of blocks. Meanwhile, in the constructor method of this class, we also write the code for creating the initial genesis block. Now we need to complete the following four methods: new_block, new_transaction, last_block, hash But there are no consensus issues in “Smart Blockchain” and neither the proof-of-work (POW) mechanism nor the proof-of-stock (POS) mechanism nor … needed. In other words, there is no need to produce a couple of alternatives of a single block like the Bitcoin and Ethereum network to let miners can choose a valid and correct block through spending billions of dollars and staggering power consumption. The following code is set exactly based on these features. hashlib json time time self.current_transactions = [] self.chain = [] self.new_block(previous_hash= ) block = { : len(self.chain) + , : time(), : self.current_transactions, : previous_hash self.hash(self.chain[ ]), } self.current_transactions = [] self.chain.append(block) block self.current_transactions.append({ : sender, : amount, : , : amount * , : recipient, : amount * , }) self.last_block[ ] + self.chain[ ] block_string = json.dumps(block, sort_keys= ).encode() hashlib.sha256(block_string).hexdigest() import import from import : class Smart_Blockchain : def __init__ (self) # Create the genesis block '1' : def new_block (self, previous_hash) """ Create a new Block in the Smart Blockchain :param previous_hash: Hash of previous Block :return: New Block """ 'index' 1 'timestamp' 'transactions' 'previous_hash' or -1 # Reset the current list of transactions return : def new_transaction (self, sender, amount, recipient) """ Creates a new transaction to go into the next mined Block :param sender: Address of the Sender :param amount_send: The amount sent by the sender :param bpsc: Address of the Smart contract (bpsc) :param amount_bpsc: The amount received by bpsc (Transaction fees) :param recipient: Address of the Recipient :param amount_receive: The amount received by the recipient :return: The index of the Block that will hold this transaction """ 'sender' 'amount_send' 'bpsc' 'bpsc_wallet_address' # Block Producer Smart Contract (bpsc) 'amount_bpsc' 0.00005 # Transaction fees 'recipient' 'amount_receive' 0.99995 return 'index' 1 @property : def last_block (self) return -1 @staticmethod : def hash (block) """ Creates a SHA-256 hash of a Block :param block: Block """ # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes True return In the above codes, there is no proof variable or nonce and there is no need to block reward. Because, as mentioned earlier, there is no consensus on “smart blockchain.” Even transaction fees could be zero. But to avoid spamming, for example, we consider 0.00005 of the total cost of each transaction. This small amount is stored in the (BPSC) smart contract, and the total cost of transactions can be used for development, etc., or even burned to create negative inflation. Negative inflation is one of the most effective ways to maintain and strengthen the value of money as well as for cryptocurrencies. We are now using the Flask framework so that we can communicate with the “smart blockchain” through requests based on the HTTP protocol platform. To do this, we create the following three methods: Request to build a new transaction and add it to a block Ask our server to mine a new block Request to return a complete list of blocks /transactions/new /mine /chain hashlib json time time urllib.parse urlparse flask Flask, jsonify, request app = Flask(__name__) blockchain = Smart_Blockchain() last_block = blockchain.last_block previous_hash = blockchain.hash(last_block) block = blockchain.new_block(previous_hash) response = { : , : block[ ], : block[ ], : block[ ], } jsonify(response), values = request.get_json() required = [ , , ] all(k values k required): , index = blockchain.new_transaction(values[ ], values[ ], values[ ]) response = { : } jsonify(response), response = { : blockchain.chain, : len(blockchain.chain), } jsonify(response), __name__ == : argparse ArgumentParser parser = ArgumentParser() parser.add_argument( , , default= , type=int, help= ) args = parser.parse_args() port = args.port app.run(host= , port=port) import import from import from import from import : class Smart_Blockchain # ..... # ..... # ..... # Instantiate the Node # Instantiate the Smart_Blockchain @app.route('/mine', methods=['GET']) : def mine () # Forge the new Block by adding it to the chain 'message' "New Block Forged" 'index' 'index' 'transactions' 'transactions' 'previous_hash' 'previous_hash' return 200 @app.route('/transactions/new', methods=['POST']) : def new_transaction () # Check that the required fields are in the POST'ed data 'sender' 'amount' 'recipient' if not in for in return 'Missing values' 400 # Create a new Transaction 'sender' 'amount' 'recipient' 'message' f'Transaction will be added to Block ' {index} return 201 @app.route('/chain', methods=['GET']) : def full_chain () 'chain' 'length' return 200 if '__main__' from import '-p' '--port' 5000 'port to listen on' '0.0.0.0' According to the above code, the server will be launched on port 5000. Of course, another way is to import sys and make the following changes to the end codes. With this, you can always specify your desired port when running. sys ..... __name__ == : app.run(host= , port=sys.argv[ ]) import if '__main__' '0.0.0.0' 1 Now we concatenate the two main parts of the code. Of course, you can , and at this point, our file name is . In the next step, we will run the server. We also use Postman to connect to the new API on the network. download all the code for this article here bpsc101.py We will start communicating with the new API by sending a POST transaction request to our server address: The information for this transaction must be entered in the Body section, and obviously, we select raw and then JSON. http://localhost:5000/transactions/new In the example above, we wanted to send one million tokens (for example, Aka tokens) from our wallet to another person (with a specific address). To do this, we sent the tokens and the request for this transaction to the server (which acts as a Block Producer Smart Contract). As you see, the server responded that this transaction would be added to the second block. Because the Genesis Block has already been defined in the code. We will now send a GET mining request to our server address: This will create the next block. The content of each block includes all performed transactions and pending ones, for instance, here, the second block is created that contains only one transaction. http://localhost:5000/mine According to the image above, the amount of fifty tokens for the transaction fee remains in the (BPSC) wallet, and the rest of the amount is sent to the final recipient by (BPSC). Of course, as mentioned before, the transaction fees will either be burned or spent on network development and so on. However, the type of spending these amounts has not been modeled yet. Now, We know that there must be two blocks in our chain’s server. To see the current chain, we send a GET chain request to our server address: http://localhost:5000/chain For further testing, you can send new requests for the transaction, and each time after a few transaction requests, you can send a mining request. Even, without having to do a transaction, you can mine an empty block. Meanwhile, the chain request determines the status of the chain for you at any time. The decentralized network for “smart blockchain” The “smart blockchain” network like Blockchain is decentralized. That’s why we need to implement a way for each node to be informed of its neighbor nodes on the network and keep a list of them. To do this, we use the set() so, each node recorded only once. We also create the following method to accept a list of new nodes in the form of URLs: /nodes/register hashlib json time time urllib.parse urlparse flask Flask, jsonify, request self.current_transactions = [] self.chain = [] self.nodes = set() self.new_block(previous_hash= ) parsed_url = urlparse(address) parsed_url.netloc: self.nodes.add(parsed_url.netloc) parsed_url.path: self.nodes.add(parsed_url.path) : ValueError( ) ....... values = request.get_json() nodes = values.get( ) nodes : , node nodes: blockchain.register_node(node) response = { : , : list(blockchain.nodes), } jsonify(response), __name__ == : argparse ArgumentParser parser = ArgumentParser() parser.add_argument( , , default= , type=int, help= ) args = parser.parse_args() port = args.port app.run(host= , port=port) import import from import from import from import : class Smart_Blockchain : def __init__ (self) # Create the genesis block '1' : def register_node (self, address) """ Add a new node to the list of nodes :param address: Address of node. Eg. 'http://192.168.0.5:5000' """ if elif # Accepts an URL without scheme like '192.168.0.5:5000'. else raise 'Invalid URL' @app.route('/nodes/register', methods=['POST']) : def register_nodes () 'nodes' if is None return "Error: Please supply a valid list of nodes" 400 for in 'message' 'New nodes have been added' 'total_nodes' return 201 if '__main__' from import '-p' '--port' 5000 'port to listen on' '0.0.0.0' Remember that in “smart blockchain” only the block producer smart contract of (BPSC) can create or mine the new block. But, the rest nodes of the network can only send a request to (BPSC) and through this receive the last chain. So we need to implement the nodes request from (BPSC) to return the last chain. To do this, we create the following method: /smart/chain hashlib json time time urllib.parse urlparse requests flask Flask, jsonify, request self.current_transactions = [] self.chain = [] self.nodes = set() self.new_block(previous_hash= ) schain = response = requests.get( ) response.status_code == : chain = response.json()[ ] schain = chain schain: self.chain = schain ....... replaced = blockchain.smart_chain() replaced: response = { : , : blockchain.chain, : len(blockchain.chain) } : response = { : , : blockchain.chain, : len(blockchain.chain) } jsonify(response), __name__ == : argparse ArgumentParser parser = ArgumentParser() parser.add_argument( , , default= , type=int, help= ) args = parser.parse_args() port = args.port app.run(host= , port=port) import import from import from import import from import : class Smart_Blockchain : def __init__ (self) # Create the genesis block '1' : def smart_chain (self) """ All nodes can receive the smart_chain """ None f'http://127.0.0.1:5000/chain' if 200 'chain' # Replace our chain if return True return False @app.route('/smart/chain', methods=['GET']) : def smart_chain () if 'message' 'Smart chain update by bpsc' 'smart chain' 'length' else 'message' 'Unsuccessful: Please try again' 'old chain' 'length' return 200 if '__main__' from import '-p' '--port' 5000 'port to listen on' '0.0.0.0' As mentioned earlier, in this example, we want to launch our server (which acts as a block producer smart contract) on the port 5000. According to the above codes, any other nodes in the network can send a request to (BPSC) and receive the last chain. The command “requests” on line 26 do the same. In other words, with one request, the last chain created by (BPSC) will replace the node’s chain. To continue, we need to concatenate the pieces of code (up to this point). You can , and so far is the name of our file. download all the code for this article here bpsc102.py But, if we want to test the method as well as the method, we need to have other nodes in the network. This means that we either have to use several machines or define different ports on the same machine. We do the second one and create the other two nodes with the port numbers 5001 and 5002 on the same machine. But, the main problem is that except the (BPSC) which is responsible for making the transaction, mining the block, and creating a chain for specific tokens (such as Aka tokens), the rest of the nodes shouldn’t be able to do such activities. Of course, it is simple and we just need to remove some of the code from other nodes such as the ability of mining and… /nodes/register /smart/chain To do this, we created the files: and the . Please see the details of these two files by clicking on them, as these modifications are not included in the article for avoiding context lengthier. In these files, compared to the original , only some of the code has been deleted and nothing has been added yet. Of course, the port number has also changed. nodes_v1_5001.py nodes_v1_5002.py bpsc102.py If you are using a VPN for any reason, you must turn it off during subsequent tests. Anyway, run all three files on separate consoles and create three nodes. This means that we will have the following nodes at the same time: Which acts as a smart contract (BPSC). One of the networks’ nodes that acts as a token sender. One of the networks’ nodes that acts as a token receiver. http://localhost:5000 http://localhost:5001 http://localhost:5002 To test, we first send two consecutive POST requests so that the node with port number 5001 is notified of its neighbor’s nodes on the network and stores the list of these nodes: http://localhost:5001/nodes/register It means, first as (BPSC) And then as another node is stored in the mentioned list. “nodes”: [“http://127.0.0.1:5000"] “nodes”: [“http://127.0.0.1:5002"] Now we want to test the method. But before this test, we’d better send at least one transaction request and then a mining request to the (BPSC). This will save a chain with two blocks in (BPSC). /smart/chain Now we send the following request, which is a GET type, to the address of the node that has port number 5001: By doing this, the node with port 5001 will receive the last chain from (BPSC). Thus, the node’s chain replaced with the latest chain created by (BPSC). http://localhost:5001/smart/chain o in “smart blockchain”, although none of the nodes can produce blockchain, all of them can make their transactions through (BPSC) and receive the last chain from (BPSC). Also, as a decentralized network, nodes can communicate with each other, and even network nodes might profit by the services of dozens of (BPSCs) because it is assumed that each (BPSC) is dedicated to one type of token. Dozens of “smart blockchains” on a decentralized network To make this seemingly complex subject, clear and transparent, we’d better implement a second chain for network nodes. Because by developing this pattern, you will be able to store dozens of parallel chains on each node. It’s simple, but it’s always good to drink more coffee. :) hashlib json time time urllib.parse urlparse requests flask Flask, jsonify, request self.current_information = [] self.chain = [] self.chain2 = [] self.nodes = set() self.new_block(previous_hash= ) parsed_url = urlparse(address) parsed_url.netloc: self.nodes.add(parsed_url.netloc) parsed_url.path: self.nodes.add(parsed_url.path) : ValueError( ) schain = response = requests.get( ) response.status_code == : chain = response.json()[ ] schain = chain schain: self.chain = schain block = { : len(self.chain2) + , : time(), : self.current_information, : previous_hash self.hash(self.chain2[ ]), } self.current_information = [] self.chain2.append(block) block self.current_information.append({ : information }) self.last_block[ ] + self.chain2[ ] block_string = json.dumps(block, sort_keys= ).encode() hashlib.sha256(block_string).hexdigest() app = Flask(__name__) blockchain = Smart_Blockchain() last_block = blockchain.last_block previous_hash = blockchain.hash(last_block) block = blockchain.new_block(previous_hash) response = { : , : block[ ], : block[ ], : block[ ], } jsonify(response), values = request.get_json() required = [ ] all(k values k required): , index = blockchain.new_information(values[ ]) response = { : } jsonify(response), response = { : blockchain.chain2, : len(blockchain.chain2), } jsonify(response), response = { : blockchain.chain, : len(blockchain.chain), } jsonify(response), values = request.get_json() nodes = values.get( ) nodes : , node nodes: blockchain.register_node(node) response = { : , : list(blockchain.nodes), } jsonify(response), replaced = blockchain.smart_chain() replaced: response = { : , : blockchain.chain, : len(blockchain.chain) } : response = { : , : blockchain.chain, : len(blockchain.chain) } jsonify(response), __name__ == : argparse ArgumentParser parser = ArgumentParser() parser.add_argument( , , default= , type=int, help= ) args = parser.parse_args() port = args.port app.run(host= , port=port) import import from import from import import from import : class Smart_Blockchain : def __init__ (self) # Create the genesis block '1' : def register_node (self, address) """ Add a new node to the list of nodes :param address: Address of node. Eg. 'http://192.168.0.5:5000' """ if elif # Accepts an URL without scheme like '192.168.0.5:5000'. else raise 'Invalid URL' : def smart_chain (self) """ All nodes can receive the smart_chain """ None f'http://127.0.0.1:5000/chain' if 200 'chain' # Replace our chain if return True return False : def new_block (self, previous_hash) """ Create a new Block in the Smart Blockchain :param previous_hash: Hash of previous Block :return: New Block """ 'index2' 1 'timestamp' 'information' 'previous_hash' or -1 # Reset the current list of transactions return : def new_information (self, information) """ Creates a new information :param information: Your information :return: The index of the Block that will hold this information """ 'information' return 'index2' 1 @property : def last_block (self) return -1 @staticmethod : def hash (block) """ Creates a SHA-256 hash of a Block :param block: Block """ # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes True return # Instantiate the Node # Instantiate the Smart_Blockchain @app.route('/mine', methods=['GET']) : def mine () # Forge the new Block by adding it to the chain 'message' "New Block Forged" 'index2' 'index2' 'information' 'information' 'previous_hash' 'previous_hash' return 200 @app.route('/information/new', methods=['POST']) : def new_information () # Check that the required fields are in the POST'ed data 'information' if not in for in return 'Missing values' 400 # Create a new information 'information' 'message' f'information will be added to Block ' {index} return 201 @app.route('/chain2', methods=['GET']) : def full_chain2 () 'chain2' 'length' return 200 @app.route('/chain', methods=['GET']) : def full_chain () 'chain' 'length' return 200 @app.route('/nodes/register', methods=['POST']) : def register_nodes () 'nodes' if is None return "Error: Please supply a valid list of nodes" 400 for in 'message' 'New nodes have been added' 'total_nodes' return 201 @app.route('/smart/chain', methods=['GET']) : def smart_chain () if 'message' 'Smart chain update by bpsc' 'smart chain' 'length' else 'message' 'Unsuccessful: Please try again' 'old chain' 'length' return 200 if '__main__' from import '-p' '--port' 5001 'port to listen on' '0.0.0.0' If you take a closer look at the above code, two parallel and independent blockchains are stored on one node. Of course, one of them is the previous “smart blockchain” and the other is a simple blockchain that has been added to the previous code to store personal data. Of course, the second blockchain could be a “smart blockchain,” and a node could use dozens of (BPSC) services in the same way. (For example, the transaction of different tokens stored in independent blockchains.) To create the second chain, two lists have been added to the previous lists. Line 12 is for storing data and Line 14 is for storing blockchain. You can check the rest of the modification yourself. The and the files are created exactly according to the above code. Please run these two files as well as the file at the same time so that you can do the following tests. nodes_v2_5001.py nodes_v2_5002.py bpsc102.py Now, we want to test the method. The file represents a node that has port number 5001. We send a request for storing personal data to this node. Of course, we know that the initial block or Genesis Block is built at first, so the server responds that this data will be added to the second block. Then we send the mining request for the same node. This will create the next block (the second block on the second chain). /chain2 nodes_v2_5001.py http://localhost:5001/information/new http://localhost:5001/mine We send the following request, which is of the GET type, to the same node: By doing this test, we make sure that the two blocks are in the second chain of our server, and the second chain has no relation with the first chain. http://localhost:5001/chain2 To make sure that the second chain does not interfere with the functionality of the “smart blockchain”, we repeat exactly the previous tests for the “smart blockchain”. That is, we first test the method for all three nodes. Then, from the node that plays the role of (BPSC), we request several transactions and multiple mining: /nodes/register http://localhost:5000/transactions/new http://localhost:5000/mine Finally, we send the following request, which is of GET type, to the address of the node that has port number 5001: http://localhost:5001/smart/chain As you can see in the pictures, the last chain created by (BPSC) substituted for the main chain (first chain) of this node. And finally, we conclude that both the “smart blockchain” and the second chain stored in this node completely independent. Planning and scheduling for mining and producing operations a block in a “smart blockchain” When a smart contract is registered onto the blockchain network, it becomes immortal. That is, as long as that blockchain network is working, no human (even the coder and owner of the smart contract) can make the slightest change in the initial content of the contract. Block producer smart contract (BPSC) has the same situation. So from the beginning, the time of mining operation (block production) should be clear and implemented in the codes. Otherwise, (BPSC) will always have to wait for the mining request to be able to mine the new block. There are three ways to schedule a (BPSC) smart contract for mining operations(block producing): A — based on time, build a new block, for example, every second or every minute. B — based on the number of transactions; for example, after every ten transactions or one hundred transactions. C — a combination of methods A and B; for example, ten seconds or ten transactions, each occurring sooner. Of course, we only implement one example of the first method. For example, suppose that after each transaction, a new block is created by (BPSC). So each block contains only one transaction. .......... values = request.get_json() required = [ , , ] all(k values k required): , index = blockchain.new_transaction(values[ ], values[ ], values[ ]) response = { : } last_block = blockchain.last_block previous_hash = blockchain.hash(last_block) block = blockchain.new_block(previous_hash) response = { : , : block[ ], : block[ ], : block[ ], } jsonify(response), .......... @app.route('/transactions/new', methods=['POST']) : def new_transaction () # Check that the required fields are in the POST'ed data 'sender' 'amount' 'recipient' if not in for in return 'Missing values' 400 # Create a new Transaction 'sender' 'amount' 'recipient' 'message' f'Transaction will be added to Block ' {index} # Forge the new Block by adding it to the chain 'message' "New Block Forged" 'index' 'index' 'transactions' 'transactions' 'previous_hash' 'previous_hash' return 201 As you see, the modifications have only been made in the method, and exactly the codes of have been added to the end of that method. We created the file by applying the same changes. You can run this file and perform your desired tests using Postman. /transactions/new /mine bpsc103.py In this case, if you send the following request to the server: (BPSC) immediately makes both the transaction and mining a block and adds it to the chain. http://localhost:5000/transactions/new Now, if, for example, you decide to send the mining request to the server: only an empty block will be minded because no transaction is expected. http://localhost:5000/mine Summary and conclusion: To simulate the (BPSC) block producer smart contract, we considered a node with a port number 5000 and implemented the following three files: This version is not final and cannot be interacted with other nodes. bpsc101.py This is the final version and all cases have been tested for this version. We tested the transaction request, the mining request, the request to send the last chain for the other nodes, and so on. bpsc102.py This version is also final, but in this version, we have added a new feature to the previous version. That is, (BPSC) required to create a new block after each transaction and add that block to its chain. bpsc103.py The ports 5001 and 5002 have the representation of other network nodes. To simulate these nodes, we implemented the following two versions: and This version is according to “Smart Blockchain” technology and final. Although these nodes cannot produce blocks, they can do their transactions through (BPSC) and also receive the last chain from (BPSC). nodes_v1_5001.py nodes_v1_5002.py and This is also final, but in this version, we have added a new feature to the previous version. It means a simple blockchain (To store personal data) has been added to the previous code. nodes_v2_5001.py nodes_v2_5002.py The coding is over and . You can also do more tests through separate machines or with friends. But bearing in mind that Python simulation, whether for blockchain or “smart blockchain,” usually doesn’t include all the necessary controls and operations. you can download all the article files here In this article, some controls were not performed; for example, the necessary controls for wallets were not performed. We also want to return all tokens to the sender if, for any reason, (BPSC) fails to send the tokens to the final recipient. But it’s not implemented into codes either. This kind of control should not be neglected in real work. Most smart contracts are written in specific languages, so-called high-level. For example, smart contracts in Ethereum blockchain are usually written in Solidity language. Fortunately, implementing this type of control with Solidity is even easier than Python. If you are interested, you can also read the following article. We have implemented exactly one "Smart Blockchain" with Solidity language: How To Build a Smart Blockchain That Prevents Double Spending: A Step-by-Step Guide The last word In this paper and several previous ones, we have shown that miners, block producers, and their activities are not an integral part of blockchain technology. Of course, it is a new and controversial idea to replace miners and block producers with smart contracts, and like any big work, there are many objections and obstacles in the way, but maintaining the status quo is not possible in the long run. For example, by increasing the volume of calculations in machine learning algorithms, we are witnessing an increase in the processing capacity of the machine at the same time. But in practice, the proof of work mechanism (POW) for Bitcoin is a real impasse. All miners are increasing their processing capacity, but to compete with each other, they still have to consume the amount of electrical power that equals the annual consumption of a country with ten million population. This is not fair. Cambridge Bitcoin Electricity Consumption Index Anyway, if you are interested in the subject, you can read our previous articles on “smart blockchain” as well as bitcoin problems. Also, if you have any questions or you see any ambiguities or errors in this article, please let us know. Somayyeh Gholami Mehran Kazeminia