def create(self): print('ok') while True: try: # sleep for the remaining seconds of interval print('ok') with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_TRANS_MAKE, b'')) *_, msgtype, content = recv_parser(s) print('content') print(content) if content == b'': time.sleep(0.001) pass else: sha = hashlib.sha256() sha.update(content[BLENGTH_TXID:]) print(content[:BLENGTH_TXID]) print('sha') print(sha.digest()) # content = Transaction.unpack(content) # content = trans_to_json(content) # r = requests.post('http://127.0.0.1:23390/transaction_post', data=content) # q = requests.post('http://127.0.0.1:23391/transaction_post', data=content) # print(r.text) # print(q.text) time.sleep(0.01) except Exception as e: print('error') time.sleep(0.01) finally: pass
def create(self): print('ok') while True: try: # sleep for the remaining seconds of interval print('ok') with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_TRANS_MAKE, b'')) *_, msgtype, content = recv_parser(s) print('content') print(content) if content == b'': time.sleep(0.1) else: sha = hashlib.sha256() sha.update(content[BLENGTH_TXID:]) print(content[:BLENGTH_TXID]) print('sha') print(sha.digest()) time.sleep(0.01) except Exception as e: print('error') time.sleep(0.1) finally: pass
def transaction(): if request.method == 'GET': return r'<!DOCTYPE html><html><body><form action="/transaction" method=POST>' \ r'To:<br><input type="text" name="to" value=""><br>Amount:<br><input ' \ r'type="text" name="amount" value="" pattern="+[0-9]"><br>Private Key:<br><textarea rows="4" ' \ r'cols="20" name="prikey" value=""></textarea><br>Input(TxID,index;):<br><textarea rows="4" cols="20" ' \ r'name="input" value=""></textarea><br><input type="submit" value="Submit"></form> </body></html>' else: receiver = request.form['to'] amount = int(request.form['amount']) prikey = request.form['prikey'].encode() ipt = request.form['input'] ipt, index = ipt.split(',') ipt = unhexlify(ipt) index = int(index) prikey = prikey.replace(b'\r\n', b'\n') prikey = prikey.replace(b'\\n', b'\n') private_key = load_pem_private_key(prikey, None, default_backend()) public_key = private_key.public_key() serialized_public = public_key.public_bytes( encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo) sha = hashlib.sha256() sha.update(serialized_public) public_key_hash = sha.digest() t_input = TransInput([(TXID(ipt), OUTPUT_INDEX(index))], public_key_hash) t_output = TransOutput([(ASSET(amount), PUBLIC_KEY_HASH(unhexlify(receiver)))]) trans = Transaction(t_input, t_output) trans.ready(private_key) result = trans_to_json(trans) fd = open('peer.txt', 'r') for line in fd.readlines(): if line != '\n': print('http://' + line.rstrip() + '/transaction_post') r = requests.post('http://' + line.rstrip() + '/transaction_post', data=result) print(r.text) fd.close() with socket.socket( socket.AF_UNIX, socket.SOCK_STREAM) as s: # submit the valid transaction s.connect(chainbase_address) s.sendall(send_handler(MsgType.TYPE_TRANS_WRITE, trans.b)) *_, msgtype, content = recv_parser(s) if msgtype == MsgType.TYPE_RESPONSE_OK: return 'ok' else: print(trans.show_trans()) return 'error'
def handle(self): """ handle messages from webchain and conchain :return: None """ handlers = { # write the submitted transaction to the transpool MsgType.TYPE_TRANS_WRITE: self.processor_trans_write, # provide transactions in the transpool MsgType.TYPE_TRANS_READ: self.processor_trans_read, # write the submitted block (the result of consensus) to the blockchain # MsgType.TYPE_BLOCK_WRITE: self.processor_block_write, # convert the lightblock to normal block and write it to the blockchain # MsgType.TYPE_LIGHTBLOCK_WRITE: self.processor_lightblock_write, # search the transaction that has the given txid MsgType.TYPE_TRANS_SEARCH_TXID: self.processor_trans_search_txid, # return the previous hash for constructing nonce MsgType.TYPE_BLOCK_PREVIOUS_HASH: self.processor_prev_hash, # send back blocks whose indexes locate in [start, end] MsgType.TYPE_BLOCK_READ: self.processor_block_read, # create Trans MsgType.TYPE_TRANS_MAKE: self.processor_trans_make, # write macro_block_header in blockchain MsgType.TYPE_MACRO_BLOCK_HEADER_WRITE: self.processor_macro_block_header_write, # append macro_block_body to corresponding macro_block_header MsgType.TYPE_MACRO_BLOCK_BODY_WRITE: self.processor_macro_block_body_write, # write micro_block and append it to corresponding macro_block_header MsgType.TYPE_MICRO_BLOCK_WRITE: self.processor_micro_block_write, # get current parent blocks for pending block MsgType.TYPE_GET_PARENT_HASH: self.processor_get_parent_hash } *_, msgtype, content = recv_parser(self.request) handlers[msgtype](content)
def test_004_previous_hash(self): with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.address) s.sendall(send_handler(MsgType.TYPE_BLOCK_PREVIOUS_HASH, b'')) header, length, msgtype, content = recv_parser(s) self.assertEqual(msgtype, MsgType.TYPE_RESPONSE_OK) self.assertEqual(len(content), 32) print(content)
def init_prev_hash(self): """get previous hash from chainbase when initializing""" with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_BLOCK_PREVIOUS_HASH, b'')) *_, msgtype, content = recv_parser(s) self.prev_hash = content print('prev_hash = ', content)
def handle(self): handlers = { MsgType.TYPE_NEW_BLOCK: self.server.on_new_block_received, MsgType.TYPE_BLOCK_READ: self.server.acquire_block, MsgType.TYPE_NODE_DISCOVER: self.server.peer.peer_discover } *_, msgtype, content = recv_parser(self.request) handlers[msgtype](content)
def add_block(self, block: Block) -> bool: """ add the block to the chainbase :param block: binary block :return: True | False """ with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_BLOCK_WRITE, block.b)) *_, msgtype, content = recv_parser(s) return msgtype == MsgType.TYPE_RESPONSE_OK
def test_002_trans_read(self): with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.address) s.sendall(send_handler(MsgType.TYPE_TRANS_READ, b'')) header, length, msgtype, content = recv_parser(s) content = batch_parser(content) for i in content: Transaction.unpack(i) self.assertEqual(msgtype, MsgType.TYPE_RESPONSE_OK) self.assertEqual(len(content), 2)
def put_miner_use(self, usage, useful) -> List: with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall( send_handler( MsgType.TYPE_MINER_USE, batch_handler( [struct.pack('=d', usage), struct.pack('=d', useful)]))) *_, msgtype, content = recv_parser(s) result = batch_parser(content) return result
def handle(self): handlers = { MsgType.TYPE_NEW_BLOCK: self.server.on_new_block_received, MsgType.TYPE_BLOCK_READ: self.server.acquire_block, MsgType.TYPE_NODE_DISCOVER: self.server.peer.peer_discover, MsgType.TYPE_NEW_LIGHTBLOCK: self.server.on_new_lightblock_received, MsgType.TYPE_MINER_CREDIT: self.server.get_miner_credit } *_, msgtype, content = recv_parser(self.request) handlers[msgtype](content)
def __get_trans(self) -> List[Transaction]: # self.chainbase_address with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_TRANS_READ, b'')) *_, msgtype, content = recv_parser(s) trans = [] # todo: the first transaction should reward the miner, # todo: the server may have a property named owner_address if msgtype == MsgType.TYPE_RESPONSE_OK: trans += batch_parser(content) return [Transaction.unpack(t) for t in trans]
def get_parent_hash(self) -> list: """ get pivot chain macro_block_header and tips in local DAG :return: a list of hash (the first hash refers to voting edge, others refer to reference edges) """ with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_GET_PARENT_HASH, None)) *_, msgtype, content = recv_parser(s) result = list() len_ = int(len(content) / 32) for i in range(len_): result.append(content[i * 32:(i + 1) * 32]) return result
def handle(self): handlers = { MsgType.TYPE_NODE_DISCOVER: self.server.peer.peer_discover, MsgType.TYPE_NEW_MACRO_BLOCK_HEADER: self.server.on_new_macro_block_header_received, MsgType.TYPE_NEW_MACRO_BLOCK_BODY: self.server.on_new_macro_block_body_received, MsgType.TYPE_NEW_MICRO_BLOCK: self.server.on_new_micro_block_received } *_, msgtype, content = recv_parser(self.request) handlers[msgtype](content)
def block(): start = request.args.get('start', type=int) end = request.args.get('end', type=int) with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(chainbase_address) s.sendall( send_handler(MsgType.TYPE_BLOCK_READ, struct.pack('=i', start) + struct.pack('=i', end))) *_, msgtype, content = recv_parser(s) content = batch_parser(content) block = [Block.unpack(i).show_block() for i in content] return jsonify(block)
def add_macro_block_body(self, macro_block_body: MacroBlockBody) -> bool: """ add the macro_block_body to the chainbase :param macro_block_body: binary macro_block_body :return: True | False """ with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall( send_handler(MsgType.TYPE_MACRO_BLOCK_BODY_WRITE, macro_block_body.b)) *_, msgtype, content = recv_parser(s) return msgtype == MsgType.TYPE_RESPONSE_OK
def add_macro_block_header(self, macro_block_header: MacroBlockHeader) -> bool: """ add the macro_block_header to the chainbase :param macro_block_header: binary macro_block_header :return: True | False """ print('in add macro') with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall( send_handler(MsgType.TYPE_MACRO_BLOCK_HEADER_WRITE, macro_block_header.b)) *_, msgtype, content = recv_parser(s) return msgtype == MsgType.TYPE_RESPONSE_OK
def get_miner_credit(self, public_key_hash, num) -> List: with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) p = time.time() * 100000000 print(struct.pack('=d', p)) s.sendall( send_handler( MsgType.TYPE_MINER_CREDIT, batch_handler([ public_key_hash, struct.pack('=d', num), struct.pack('=d', p) ]))) *_, msgtype, content = recv_parser(s) result = batch_parser(content) return result
def transaction_post(): temp = str(request.get_data(), encoding='utf-8') trans = json_to_trans(temp) with socket.socket( socket.AF_UNIX, socket.SOCK_STREAM) as s: # submit the valid transaction s.connect(chainbase_address) s.sendall(send_handler(MsgType.TYPE_TRANS_WRITE, trans.b)) *_, msgtype, content = recv_parser(s) # print('end.....') # print(content) if msgtype == MsgType.TYPE_RESPONSE_OK: return 'ok' else: return 'error'
def handle(self): """ handle messages from webchain and conchain :return: None """ handlers = { # write the submitted transaction to the transpool MsgType.TYPE_TRANS_WRITE: self.processor_trans_write, # provide transactions in the transpool MsgType.TYPE_TRANS_READ: self.processor_trans_read, # write the submitted block (the result of consensus) to the blockchain MsgType.TYPE_BLOCK_WRITE: self.processor_block_write, # convert the lightblock to normal block and write it to the blockchain # MsgType.TYPE_LIGHTBLOCK_WRITE: self.processor_lightblock_write, # search the transaction that has the given txid MsgType.TYPE_TRANS_SEARCH_TXID: self.processor_trans_search_txid, # return the previous hash for constructing nonce MsgType.TYPE_BLOCK_PREVIOUS_HASH: self.processor_prev_hash, # send back blocks whose indexes locate in [start, end] MsgType.TYPE_BLOCK_READ: self.processor_block_read, # create Trans MsgType.TYPE_TRANS_MAKE: self.processor_trans_make # get miner's credit # MsgType.TYPE_MINER_CREDIT: self.processor_miner_credit, } *_, msgtype, content = recv_parser(self.request) handlers[msgtype](content)
def __get_trans(self) -> List[Transaction]: # self.chainbase_address with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_TRANS_READ, b'')) *_, msgtype, content = recv_parser(s) trans = [] if msgtype == MsgType.TYPE_RESPONSE_OK: trans += batch_parser(content) private_key = ec.generate_private_key(ec.SECP256K1, default_backend()) public_key = private_key.public_key() public_key = public_key.public_bytes( Encoding.DER, PublicFormat.SubjectPublicKeyInfo) sha = hashlib.sha256() sha.update(public_key) public_key_hash = sha.digest() ipt = TransInput([(TXID(public_key_hash), OUTPUT_INDEX(0))], public_key_hash) fd_ = open('ad1.txt', 'r') for index, line in enumerate(fd_.readlines()): if index == 0: line = line.rstrip() pr, pu = line.split('ENDDING') temp = bytes(pu[2:-1], encoding='utf-8') temp = temp.replace(b'\r\n', b'\n') public_key = temp.replace(b'\\n', b'\n') sha = hashlib.sha256() sha.update(public_key) public_key_hash = sha.digest() break fd_.close() opt = TransOutput([(ASSET(20), public_key_hash)]) tran = Transaction(ipt, opt, 0) tran.ready(private_key) trans.append(tran.b) # result = self.get_miner_credit(public_key_hash, 5) # print(result) print('len = ', len(trans)) return [Transaction.unpack(t) for t in trans]
def __get_trans(self) -> List[Transaction]: with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: s.connect(self.chainbase_address) s.sendall(send_handler(MsgType.TYPE_TRANS_READ, b'')) *_, msgtype, content = recv_parser(s) trans = [] if msgtype == MsgType.TYPE_RESPONSE_OK: trans += batch_parser(content) private_key = ec.generate_private_key(ec.SECP256K1, default_backend()) public_key = private_key.public_key() public_key = public_key.public_bytes( Encoding.DER, PublicFormat.SubjectPublicKeyInfo) sha = hashlib.sha256() sha.update(public_key) public_key_hash = sha.digest() ipt = TransInput([(TXID(public_key_hash), OUTPUT_INDEX(0))], public_key_hash) opt = TransOutput([(ASSET(20), PUBLIC_KEY_HASH(miner_public_key_hash))]) tran = Transaction(ipt, opt, 0) tran.ready(private_key) trans.append(tran.b) content = trans_to_json(tran) requests.post('http://127.0.0.1:23390/transaction_post', data=content) if self.block_num < -50: self.get_miner_credit(miner_public_key_hash, 0.5 / self.block_num) else: self.get_miner_credit(miner_public_key_hash, 0.5) # print(struct.unpack('=d', result[0]), struct.unpack('=d', result[1])) return [Transaction.unpack(t) for t in trans]
def handle(self): handlers = {} *_, msgtype, content = recv_parser(self.request) handlers[msgtype](content)
def test_000_trans_write(self): """ The first (genesis) block contains a transaction that pays 42 to the address that corresponds to the following private key. This test case first use this private key to issue and submit a transaction which pays 7 for 6 random addresses. This transaction is valid and stays in the pool of transactions. Then the test try to issue a new transaction. Because the 42 assets of the following private key were used up, the new transaction is invalid. Finally, the test pays 7 from random address 1 to address 2. """ tinput = [( b'O\x1e,-\xe1\xa0!\x16D\x87\xcc\x923\xf7\xf6\xca\xad\xd1\t\x8eV\xdc\xe8t}N\xfa\x8af\xbe\xe7\xef', 0)] private_key1 = load_pem_private_key( b'-----BEGIN PRIVATE KEY-----\nMIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0w' b'awIBAQQg64DiDBUkuGC5rrTfH6uy\nHt6vhvHrMHj3Gm64SZtdqtKhRANCAATMIea' b'IK4vT0ni00F6GGW40qioinPFgXjsj\n6sZGivW9Ipj+zcDfPc7RxZuFeKFmbtVaUX' b'Z877DM4C8ELZs2DPVQ\n-----END PRIVATE KEY-----\n', None, default_backend()) public_key = b'-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzCHmiCuL09J4tNBehhluNKoqIpzx' \ b'YF47\nI+rGRor1vSKY/s3A3z3O0cWbhXihZm7VWlF2fO+wzOAvBC2bNgz1UA==\n-----END PUBLIC KEY-----\n' sha = hashlib.sha256() sha.update(public_key) public_key_hash = sha.digest() T1 = TransInput(tinput, public_key_hash) public_key_hash = [] private_keys = [] public_keys = [] for i in range(6): private_key = ec.generate_private_key(ec.SECP256K1, default_backend()) private_keys.append(private_key) public_key = private_key.public_key() public_key = public_key.public_bytes( Encoding.PEM, PublicFormat.SubjectPublicKeyInfo) public_keys.append(public_key) sha = hashlib.sha256() sha.update(public_key) public_key_hash.append(sha.digest()) toutput = [(7, public_key_hash[i]) for i in range(6)] T2 = TransOutput(toutput) T = Transaction(T1, T2) T.ready(private_key1) with socket.socket( socket.AF_UNIX, socket.SOCK_STREAM) as s: # submit the valid transaction s.connect(self.address) payload = send_handler(MsgType.TYPE_TRANS_WRITE, T.b) s.sendall(payload) header, length, msgtype, content = recv_parser(s) self.assertEqual(content, b'') self.assertEqual(length, 0) self.assertEqual( msgtype, MsgType.TYPE_RESPONSE_OK) # the chainbase returns OK with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: # submit the same transaction, but it is invalid this time s.connect(self.address) payload = send_handler(MsgType.TYPE_TRANS_WRITE, T.b) s.sendall(payload) header, length, msgtype, content = recv_parser(s) self.assertEqual(content, b'') self.assertEqual(length, 0) self.assertEqual( msgtype, MsgType.TYPE_RESPONSE_ERROR) # the chainbase returns ERROR """ construct a second valid transaction, which pay 7 from random address 1 to random address 2 """ private_key = private_keys[0] public_key = public_keys[0] public_key_hash1 = public_key_hash[0] T1 = TransInput([(T.txid, 0)], public_key_hash1) toutput = [(7, public_key_hash[1])] T2 = TransOutput(toutput) T = Transaction(T1, T2) T.ready(private_key) with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM ) as s: # submit the second valid transaction s.connect(self.address) payload = send_handler(MsgType.TYPE_TRANS_WRITE, T.b) s.sendall(payload) header, length, msgtype, content = recv_parser(s) self.assertEqual(content, b'') self.assertEqual(length, 0) self.assertEqual( msgtype, MsgType.TYPE_RESPONSE_OK) # the chainbase returns OK
def test_001_block_write(self): """ use the same case as the test_000_trans_write, but transactions are seperated into different blocks :return: """ # replace the following connection address with the address in the chainbase tinput = [( b'O\x1e,-\xe1\xa0!\x16D\x87\xcc\x923\xf7\xf6\xca\xad\xd1\t\x8eV\xdc\xe8t}N\xfa\x8af\xbe\xe7\xef', 0)] private_key1 = load_pem_private_key( b'-----BEGIN PRIVATE KEY-----\nMIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0w' b'awIBAQQg64DiDBUkuGC5rrTfH6uy\nHt6vhvHrMHj3Gm64SZtdqtKhRANCAATMIea' b'IK4vT0ni00F6GGW40qioinPFgXjsj\n6sZGivW9Ipj+zcDfPc7RxZuFeKFmbtVaUX' b'Z877DM4C8ELZs2DPVQ\n-----END PRIVATE KEY-----\n', None, default_backend()) public_key = b'-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzCHmiCuL09J4tNBehhluNKoqIpzx' \ b'YF47\nI+rGRor1vSKY/s3A3z3O0cWbhXihZm7VWlF2fO+wzOAvBC2bNgz1UA==\n-----END PUBLIC KEY-----\n' sha = hashlib.sha256() sha.update(public_key) public_key_hash = sha.digest() T1 = TransInput(tinput, public_key_hash) public_key_hash = [] private_keys = [] public_keys = [] for i in range(6): private_key = ec.generate_private_key(ec.SECP256K1, default_backend()) private_keys.append(private_key) public_key = private_key.public_key() public_key = public_key.public_bytes( Encoding.PEM, PublicFormat.SubjectPublicKeyInfo) public_keys.append(public_key) sha = hashlib.sha256() sha.update(public_key) public_key_hash.append(sha.digest()) toutput = [(7, public_key_hash[i]) for i in range(6)] T2 = TransOutput(toutput) T = Transaction(T1, T2) T.ready(private_key1) pri_key = private_keys[0] public_key_hash1 = public_key_hash[0] T8 = TransInput([(T.txid, 0)], public_key_hash1) toutput = [(7, public_key_hash[1])] T9 = TransOutput(toutput) T4 = Transaction(T8, T9) T4.ready(pri_key) at = Attachment() at.add_data(b'') at.ready() bd = BlockData([T, T4], at) t = time.time() block = Block( 1, t, bd, b'G\xfdk\x88\xda5\xff\x8c\x97t\x9f\xcb\xe0\xa8\x07S\x8b9t:.9\x1d\xee\xf4\xb1\xda\xd1r\xaf\xfcu', 33) """ construct a second valid transaction, which pay 7 from random address 1 to random address 2 """ with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM ) as s: # submit the second valid transaction s.connect(self.address) payload = send_handler(MsgType.TYPE_BLOCK_WRITE, block.b) s.sendall(payload) header, length, msgtype, content = recv_parser(s) self.assertEqual(content, b'') self.assertEqual(length, 0) self.assertEqual( msgtype, MsgType.TYPE_RESPONSE_OK) # the chainbase returns OK