def presentblock(endpoint, blockJSON): block = dbinterface.blockfromJSON(blockJSON) halfhour = timedelta(minutes=30) context = dbinterface.getEndpointContext(block.endpoint) print("chain length before acceptance is: {}".format(context[2])) # We should check if the message came from the endorser. If not, we should # check with the endorser in the block. This is not implemented due to time # constraints. if not dbinterface.isInLedgers(endpoint): return "block rejected, endpoint not known" if block.endpoint != endpoint: return "block rejected, endpoint doesn't match" if block.index > context[2] + 1: return "block rejected, lacking previous blocks" if block.operation != "ADD" and block.operation != "REV" and block.operation != "SMP": return "block rejected, operation unknown" if (datetime.now() - halfhour > datetime.fromtimestamp(block.timestamp) or datetime.now() + halfhour < datetime.fromtimestamp( block.timestamp)): return "block rejected, timestamp off" # if block.previous_hash != dbinterface.getBlock(block.index - 1, endpoint).compute_hash(): # previous block mismatch # return "block rejected, hash mismatch" dbinterface.getBlock(block.index - 1, endpoint).compute_hash() #TODO: reject block if a copy is already known #TODO: reject block if whitebox is already known #TODO: reject block for other reasons #TODO: Drop blocks that may now be invalid, or reject block for stored block with precedent #TODO: store block if accepted if block.index == context[2] + 1: dbinterface.addBlock(block, endpoint) return "block accepted" else: #TODO: compare block with stored block for timestamp, find correct chain, # reject other chain. print("index wrong: got {}, should be {}".format( block.index, context[2] + 1)) return "block accepted, but not stored(implementation)"
def validatestoredledger(endpoint, endorsercount): context = dbinterface.getEndpointContext(endpoint) if context[1] != endpoint: return False lastblock = dbinterface.getBlock(context[2], endpoint) lasthash = lastblock.compute_hash() #TODO: local hash validation # Remote validation references = downloadremotereferences(endpoint, endorsercount) successes = 0 for reference in references: request_url = "http://{}/getlastblockhash/{}".format( reference, endpoint) r = requests.get(request_url) print("received hash: {} my hash: {}".format(r.text, lasthash)) if r.text == lasthash: successes += 1 if successes > endorsercount / 2: return True return False
def revoketrust(endpoint): context = dbinterface.getContext() endpointContext = dbinterface.getEndpointContext(endpoint) if dbinterface.isInLedgers(endpoint): prev_block_hash = dbinterface.getBlock(endpointContext[2], endpoint).compute_hash() my_registration_block = Block(endpointContext[2] + 1, "REV", datetime.timestamp(datetime.now()), 1, prev_block_hash, context[1], endpoint) if pushblocktopeers(endpoint, my_registration_block, 3): dbinterface.addBlock(my_registration_block, endpoint) dbinterface.deleteLedgerEntry(endpoint) os.remove("{}.db".format(endpoint)) return "Trust succesfully revoked" else: return "block push to peers failed. Revoke failed." else: return "endpoint {} not known, no trust exists to be revoked".format( endpoint)
def trust(endpoint): """ Establish this whitebox as a endorser for endpoint. """ context = dbinterface.getContext() if dbinterface.isInLedgers(endpoint): #Ledger is locally available, therefore the whitebox already endorses endpoint return "Whitebox is already an endorser" else: request_url = "{}/getnumendorsers/{}".format(discovery_server, endpoint) r = requests.get(request_url) if r.status_code != 200: return "Discovery server error, endorse failed" if r.text == "0": #entirely new ledger msg = setupNewLedger(endpoint) request_url = "{}/register@{}&{}".format(discovery_server, context[1], endpoint) r = requests.get(request_url) if r.status_code == 200: if r.text == "now endorsing endpoint " + str(endpoint): print( "Registration succeeded, but other registration already exists. Should now discover other endorser, but this is not implemented" ) else: print( "Registration failed. Should be retried automatically, but this is not implemented" ) return msg else: #ledger exists elsewhere other_endorsers_count = int(r.text) references_used = other_endorsers_count if references_used > verify_with_count: references_used = verify_with_count reference = downloadremotereferences(endpoint, 1)[0] downloadremoteledger(endpoint, reference) if validatestoredledger(endpoint, references_used): # make ledgers entry with sl.connect('trustledgers.db') as con: con.execute('INSERT INTO LEDGERS (id, name) values(?, ?)', (context[2] + 1, endpoint)) dbinterface.setNumledgers(context[2] + 1) endpointContext = dbinterface.getEndpointContext(endpoint) #make registration block prev_block_hash = dbinterface.getBlock( endpointContext[2], endpoint).compute_hash() my_registration_block = Block( endpointContext[2] + 1, "ADD", datetime.timestamp(datetime.now()), 1, prev_block_hash, context[1], endpoint) # add block to own ledger dbinterface.addBlock(my_registration_block, endpoint) if not pushblocktopeers(endpoint, my_registration_block, 2): return "Trust-link failed, coulnd't establish with peers. Should be retried later automatically, but this is not implemented" # register with discovery_server request_url = "{}/register@{}&{}".format( discovery_server, context[1], endpoint) r = requests.get(request_url) if r.status_code == 200: return "Trust-link succesfully established" else: return "Trust-link establishment succeeded, but discovery server registration failed. Should retry automatically, but this is not implemented" else: return "Trust-link failed, ledger verification failed" return 'trust failed'
def getlastblockhash(endpoint): context = dbinterface.getEndpointContext(endpoint) if context[1] != endpoint: return False lastblock = dbinterface.getBlock(context[2], endpoint) return lastblock.compute_hash()