def sync(state): peer_nodes = state.peer_nodes longest_peer, max_id = get_longest_peer(peer_nodes) if max_id > get_last_block()['index']: LOG.debug("%s(%s) is larger than %s(local max)" % (max_id, longest_peer, state.block['index'])) sync_block_range(longest_peer, state.block['index'], max_id, state)
def get_longest_peer(peer_nodes): max_id = 0 peer_node = '' for peer in peer_nodes: LOG.debug("Get %s/block info" % peer) r = requests.get("%s/block" % peer) if r.status_code == 200: LOG.debug("Remote block id is %ss" % r.json()['index']) if r.json()['index'] > max_id: max_id = r.json()['index'] peer_node = peer return peer, max_id
def create_genesis_block(genesis_json, miner_address): ''' create the Gendsis Block ''' data = {} alloc = genesis_json.get('alloc', {}) data[u'trans'] = [] if alloc: trans = [] for k, v in alloc.items(): _trans = {u"from": 0, u"to": k, u"assets": v} LOG.info("intial alloc is: %s" % _trans) trans.append(_trans) transfer.transfer_save(json.dumps(_trans)) data[u'trans'] = trans coin_trans = utils.get_reward_trans(0, miner_address) data[u'trans'].insert(0, coin_trans) data[u'info'] = genesis_json return Block(0, str(time.time()), data, "0")
def check(self): block_file_name = options.block_path_format % ( options.chain_dir, hex(self.dict()['index'])) if os.path.isfile(block_file_name): LOG.info("block %s is exist, pass" % self.dict()['index']) return False if self.sync: LOG.debug("block content check") if self.hash != self.hash_block(self.nonce): LOG.info("hash is not correct, %s(send) != %s(generate)" % (self.hash, self.hash_block(self.nonce))) return False if self.index != 0: previous_block = get_block_by_id(self.index - 1) if self.previous_hash != previous_block['hash']: LOG.info("hash is not continuity") return False if (self.data['trans'][0]['assets']['coin'] - fee) != utils.get_reward(self.index): LOG.info("reward is not correct, %s - %s != %s" % \ (self.data['trans'][0]['assets']['coin'], \ fee, utils.get_reward(self.index))) return False return True
def transfer(trans, utxo): LOG.debug("trans assets: %s" % trans['assets']) for k, v in trans['assets'].items(): if float(v) > float(utxo['assets'].get(k, 0)): LOG.debug("trans %s is large than %s" % s(v, utxo['assets'][k])) return False, {} else: utxo['assets'][k] -= float(v) utxo['assets']['coin'] -= trans['fee'] if utxo['assets']['coin'] < 0: LOG.debug("utxo is not enouth to pay fee: %s" % utxo['assets']['coin']) return False, {} for v in utxo['assets'].values(): if v: return True, utxo['assets']
def save(self): ''' save block file as a file to disk ''' if not self.check(): LOG.info("block check failed") return False block_file_name = options.block_path_format % ( options.chain_dir, hex(self.dict()['index'])) LOG.debug("block %s trans is %s" % (self.dict()['index'], self.dict()['data']['trans'])) for _trans in self.dict()['data']['trans']: transfer.transfer_save(json.dumps(_trans)) block_file = file(block_file_name, 'w') block_file.write(str(json.dumps(self.dict()))) file(options.block_path_format % (options.chain_dir, 'head'), 'w').write(json.dumps({"max": self.dict()['index']})) LOG.debug("block %s is save with %s" % (self.dict()['index'], block_file_name))
def utxo_transfer(trans): try: utxo = get_utxo_by_id(trans) _addr = account.get_addr(trans['publickey']) #if utxo['to'] != _addr: #LOG.debug("address is pair or not, %s != %s" % (utxo['to'], _addr)) #return (False, {}, {}) LOG.debug("address is pair %s -> %s" % (utxo['to'], _addr)) account.verify(trans['signout'], trans['publickey'], trans['from']) except: LOG.debug("signout is pair or not") return (False, {}, {}) result, new_assets = transfer(trans, utxo) if result and new_assets: LOG.debug("new assets after trans is %s" % new_assets) utxo['to'] = trans.get('returnto') or utxo['to'] utxo['assets'] = new_assets fee = float(trans['fee']) / 2 trans[u'fee'] = utxo[u'fee'] = fee else: utxo = {} #os.remove(options.trans_path_format % (options.chain_dir, trans['from'])) return (True, trans, utxo)
def post(self): ''' transaction data: { "from": "6453cbef347928491159770529f4a8b64de410eca353c8d20ca7eef7f5f214e7", #utxo hash "to": "5NRKJc2QHkHk7vhmSamW9UEDeYUoWLQJW8", # address to pay "publickey": "", # account's public key "singout": "", # hash sign by account private key "returnto": "8rP4v7r7bfpyo2XGHjP1wCanvVqDgZFrp4", #Remaining assets back address "assets": { "coin": 1 } } ''' LOG.debug("memary trans len is %s" % len(self.state.trans)) LOG.debug(self.state.trans) trans = json.loads(self.request.body.decode('utf-8')) transable, trans, return_trans = transfer.utxo_transfer(trans) if not transable: LOG.debug("trans check result: %s" % transable) self.write({'result':'failed'}) return LOG.debug(" From %s to %s" % (trans['from'], trans['to'])) for k, v in trans['assets'].items(): LOG.debug("\t%s%s transfer from %s to %s" % (v, k, trans['from'], trans['to'])) return_utxo = self.trans(trans, return_trans) LOG.debug("new memary trans len is %s" % len(self.state.trans)) LOG.debug(self.state.trans) self.write(json.dumps({"result":"success", "return_utxo":return_utxo}))