Exemplo n.º 1
0
        def transactions():
            start = request.args.get('from')
            if not start or start == "":
                next = client.chain[-1]
            else:
                next = base64.urlsafe_b64decode(start.encode('UTF-8'))

            length = request.args.get('length')
            if not length:
                length = 25
            else:
                length = int(length)

            length = min(length, len(client.chain)-3)

            transactions = []
            for entries in range(length):
                block_bytes = client.chain[next][:-32]
                block = trustchain_pb2.Block()

                block.ParseFromString(block_bytes)
                transaction = trustchain_pb2.Transaction()
                transaction.ParseFromString(block.transaction)
                myID = None
                for i in range(len(transaction.ID)):
                    if transaction.ID[i] == bytes(client.verify_key):
                        myID = i
                if myID == 1:
                    value = transaction.value * -1
                else:
                    value = transaction.value
                next = transaction.previousHash[myID]
                transactions.append(((time.strftime("%b %d %Y %H:%M:%S",
                    time.gmtime(transaction.timestamp))),
                    client.friendlyNameList[transaction.ID[1-myID]], "EUR {0:.2f}".format(value), base64.urlsafe_b64encode(next).decode('UTF-8')))

                if next == b'\x00':
                    break

            return jsonify({"from": base64.urlsafe_b64encode(next).decode('UTF-8'), "transactions": transactions}), 200, {'Access-Control-Allow-Origin': '*'}
Exemplo n.º 2
0
    def verify_block(block_bytes):
        hash = block_bytes[-32:]
        block_bytes = block_bytes[:-32]

        if hash != nacl.hash.sha256(block_bytes,
                                    encoder=nacl.encoding.RawEncoder):
            raise ValueError("Hashes do not match")
        block = trustchain_pb2.Block()
        block.ParseFromString(block_bytes)

        transaction = trustchain_pb2.Transaction()
        transaction.ParseFromString(block.transaction)

        if len(transaction.ID) != len(block.signatures):
            print(transaction)
            print(block)
            raise ValueError(
                "Number of signatures don't match with the number of ID's")

        for i in range(0, len(transaction.ID)):
            try:
                verify_key = nacl.signing.VerifyKey(transaction.ID[i])
                verify_key.verify(block.transaction, block.signatures[i])
            except nacl.exceptions.BadSignatureError as e:
                raise ValueError(e)

        if round(time.time()) < transaction.timestamp:
            raise ValueError(
                "Block claims to be created in the future. current time {}, creation time {}"
                .format(
                    time.strftime("%Y-%m-%d %H:%M:%S", (time.gmtime())),
                    time.strftime("%Y-%m-%d %H:%M:%S",
                                  (time.gmtime(transaction.timestamp)))))

        if transaction.value == 0:
            # Transaction is genesis block
            pass

        return block, hash
Exemplo n.º 3
0
    def create_genesis_block(self):
        '''
        Genesis block:
        | 0x00 | Timestamp | creator ID | Signature | Hash |
            1  +  4 bytes  +  32 bytes  +  64 bytes +  32  =  133
        '''
        ID = bytes(self.signing_key.verify_key)
        block = trustchain_pb2.Block()
        # create empty transaction
        transaction = trustchain_pb2.Transaction()
        transaction.timestamp = 0
        transaction.value = 0
        transaction.ID.append(ID)
        transaction.previousHash.append(b'\0')
        transaction.sequence_no.append(0)
        transaction.balance.append(1000)

        block.transaction = transaction.SerializeToString()
        block.signatures.append(
            self.signing_key.sign(block.transaction).signature)
        serial_block = block.SerializeToString()
        hash = nacl.hash.sha256(serial_block, encoder=nacl.encoding.RawEncoder)
        return serial_block + hash
Exemplo n.º 4
0
import Core.trustchain_pb2 as trustchain

if __name__ == '__main__':
    block = trustchain.Block()
    block.timestamp = 123
    block.sequence_no = 1
    block.ID.append(b"ASDFASDFASDF")
    henk = block.ID
    block.payload = b'321'

    print(block)
    waardes = block.SerializeToString()
    print(waardes, '\n')
    anderblock = trustchain.Block()
    anderblock.ParseFromString(waardes)
    print(anderblock)
Exemplo n.º 5
0
    def fsm(self, message):
        # # Statemachine implementation (See notes.pptx for diagram)
        # States for initiator node
        reply = b'\x00' # Always default to nack
        if self.state == 0:
            if message[:1] == b'\x01':
                trade_request = trustchain_pb2.TradeRequest()
                trade_request.ParseFromString(message[1:])

                self.counter_party = trade_request.publicKey
                self.trade_value = trade_request.value

                if self.counter_party not in self.addressList:
                    logging.warning("Incoming transaction from unknown id {}".format(self.counter_party))
                    return reply
                logging.info("Incoming transaction from {}".format(self.friendlyNameList[self.counter_party]))

                try:
                    counter_block, self.counter_party_prev_hash = self.trustchain.verify_block(trade_request.blocks[0])
                except ValueError:
                    logging.exception("Found invalid block in trade request")
                    return reply


                counter_transaction = trustchain_pb2.Transaction()
                counter_transaction.ParseFromString(counter_block.transaction)

                block_is_valid = False
                for i in range(0, len(counter_transaction.ID)):
                    if counter_transaction.ID[i] == self.counter_party:
                        self.counter_balance = counter_transaction.balance[i]
                        self.counter_party_sequenceNo = counter_transaction.sequence_no[i]
                        block_is_valid = True
                        break

                # Todo: re-enable balance check for normal usage
                if self.counter_balance < self.trade_value:
                    logging.warning("Value is more than balance! value is {}, received last block is: \n {} \n THIS WILL BE INGORED FOR DEMONSTRATION PURPOSES".format(self.trade_value ,str(counter_transaction)))
                    # return reply

                if block_is_valid:
                    transaction = trustchain_pb2.Transaction()
                    transaction.timestamp = round(time.time())

                    transaction.previousHash.append(self.chain[-1])
                    transaction.previousHash.append(self.counter_party_prev_hash)

                    transaction.sequence_no.append(self.sequenceNo + 1)
                    transaction.sequence_no.append(self.counter_party_sequenceNo + 1)

                    transaction.ID.append(bytes(self.signing_key.verify_key))
                    transaction.ID.append(self.counter_party)

                    transaction.value = self.trade_value

                    transaction.balance.append(self.balance + self.trade_value)
                    transaction.balance.append(self.counter_balance - self.trade_value)

                    # Create a block for the counter party to sign
                    block = trustchain_pb2.Block()
                    block.transaction = transaction.SerializeToString()
                    block.signatures.append(self.signing_key.sign(block.transaction).signature)
                    self.proposed_block = block

                    trade_reply = trustchain_pb2.TradeReply()
                    trade_reply.proposedBlock = block.SerializeToString()
                    trade_reply.blocks.append(self.chain[self.chain[-1]])

                    #  trade_ack, + last block
                    reply = b'\02' + trade_reply.SerializeToString()
                    self.state = 2
            return reply

        # Wait for trade reply
        if self.state == 1:
            if message[:1] == b"\x02":  # 2 is trade_reply
                trade_reply = trustchain_pb2.TradeReply()
                trade_reply.ParseFromString(message[1:])
                # Verify block
                try:
                    counter_block, self.counter_party_prev_hash = self.trustchain.verify_block(trade_reply.blocks[0])
                except ValueError:
                    return reply
                # todo: make the following code work for multiple blocks
                chain = trustchain_pb2.Chain()
                chain.blocks.append(self.chain[self.chain[-1]])

                counter_chain = trustchain_pb2.Chain()
                counter_chain.blocks.append(trade_reply.blocks[0])

                counter_transaction = trustchain_pb2.Transaction()
                counter_transaction.ParseFromString(counter_block.transaction)

                block_is_valid = False
                for i in range(0, len(counter_transaction.ID)):
                    if counter_transaction.ID[i] == self.counter_party:
                        self.counter_balance = counter_transaction.balance[i]
                        self.counter_party_sequenceNo = counter_transaction.sequence_no[i]
                        block_is_valid = True
                        break
                # shit down is copied from previous itteration
                try:
                    block = trustchain_pb2.Block()
                    block.ParseFromString(trade_reply.proposedBlock)

                    transaction = trustchain_pb2.Transaction()
                    transaction.ParseFromString(block.transaction)
                except ValueError as e:
                    print(e)
                    return reply

                if len(block.signatures) != 1:
                    print(transaction)
                    print(block)
                    raise ValueError("WTF, dit  block is helemaal niet getekend f****r")

                # Check if the values are actually the values you agreed uppon
                for i in range(0, len(transaction.ID)):
                    if self.trade_value != transaction.value:
                        raise ValueError("trade agreed on {}".format(self.trade_value))
                    # Checks for Counter party
                    if transaction.ID[i] == self.counter_party:
                        if self.counter_balance + self.trade_value != transaction.balance[i]:
                            block_is_valid = False
                            print(transaction)
                            print("Counter balance don't match old {}".format(self.counter_balance))
                        if self.counter_party_prev_hash != transaction.previousHash[i]:
                            block_is_valid = False
                            print(transaction)
                            print("Counter hash don't match {}".format(self.counter_party_prev_hash))
                        if self.counter_party_sequenceNo + 1!= transaction.sequence_no[i]:
                            block_is_valid = False
                            print(transaction)
                            print(" Counter sequence NO don't match {}".format(self.counter_party_sequenceNo))
                    # Checks for mine
                    if transaction.ID[i] == bytes(self.signing_key.verify_key):
                        if self.balance - self.trade_value != transaction.balance[i]:
                            block_is_valid = False
                            print(transaction)
                            print("my balance don't match old {}".format(self.balance))
                        if self.chain[-1][-32:] != transaction.previousHash[i]:
                            block_is_valid = False
                            print(transaction)
                            print("my hash don't match {}".format(self.chain[-1][-32:]))
                        if self.sequenceNo + 1 != transaction.sequence_no[i]:
                            block_is_valid = False
                            print(transaction)
                            print("My sequence NO don't match {}".format(self.sequenceNo))

                if block_is_valid:
                    block.signatures.append(self.signing_key.sign(block.transaction).signature)
                else:
                    return reply

                self.proposed_block = block
                if self.required_Witnesses > 0:
                    request = trustchain_pb2.SignatureRequest()
                    request.transaction = transaction.SerializeToString()

                    request.chains.add().CopyFrom(counter_chain)
                    request.chains.add().CopyFrom(chain)

                    gevent.spawn(self.collect_signatures, request, self.required_Witnesses, self.fwsp_reply)

                    try:
                        sigs = self.fwsp_reply.get(block=True, timeout=0.5)
                        if len(sigs) == 0:
                            logging.error("Transaction failed, not enough valid witnesses")
                            # print("Aaawh FWSP failed")
                            return reply
                    except gevent.timeout.Timeout:
                        logging.info("Sending keep alive message: not enough valid witness replies.")
                        reply = b'\x03' + self.fwsp_no_sigs.to_bytes(4,byteorder='big',signed=False)
                        self.state = 3
                        return reply

                    self.proposed_block.witnesses.extend(sigs)
                    logging.info("Transaction successful with {}/{} valid witness replies".format(len(sigs),
                                                                                              self.required_Witnesses))
                block_bytes = self.proposed_block .SerializeToString()
                block = block_bytes + nacl.hash.sha256(block_bytes, encoder=nacl.encoding.RawEncoder)

                self.chain[block[-32:]] = block
                self.chain[-1] = block[-32:]
                self.balance = self.balance - self.trade_value
                self.sequenceNo = self.sequenceNo + 1
                reply = b'\x05' + block
            return reply

        # Had to send keep alive message
        if self.state == 3:
            if message[:1] == b"\x04":
                try:
                    sigs = self.fwsp_reply.get(block=True, timeout=0.5)
                    if len(sigs) == 0:
                        logging.error("Transaction failed, not enough valid witnesses")
                        return reply
                except gevent.timeout.Timeout:
                    logging.info("Sending keep alive message: not enough valid witness replies.")
                    reply = b'\x03' + self.fwsp_no_sigs.to_bytes(4,byteorder='big',signed=False)
                    return reply

                self.proposed_block.witnesses.extend(sigs)
                logging.info("Transaction successful with {}/{} valid witness replies".format(len(sigs),
                                                                                              self.required_Witnesses))
                block_bytes = self.proposed_block.SerializeToString()
                block = block_bytes + nacl.hash.sha256(block_bytes, encoder=nacl.encoding.RawEncoder)

                self.chain[block[-32:]] = block
                self.chain[-1] = block[-32:]
                self.balance = self.balance - self.trade_value
                self.sequenceNo = self.sequenceNo + 1
                reply = b'\x05' + block
                return reply

        if self.state == 2:
            if message[:1] == b"\x05":
                block = message[1:]
                try:
                    received_block, hash = TrustChain.verify_block(block)
                except ValueError:
                    logging.exception("Malformed block received in final stage\n")
                    return reply

                if self.proposed_block.transaction != received_block.transaction:
                    logging.warning("Block does not contain transaction earlier agreed uppon")
                    return reply
                valid_witnesses = 0
                for aproval in received_block.witnesses:
                    try:
                        TrustChain.verify_witness_reply(received_block.transaction, aproval)
                        valid_witnesses += 1
                    except ValueError:
                        logging.exception("Error occured during the verification of witness replies in teh block")

                logging.info("Transaction successful with {}/{} witness".format(valid_witnesses, self.required_Witnesses))
                self.chain[block[-32:]] = block
                self.chain[-1] = block[-32:]
                self.balance = self.balance + self.trade_value
                self.sequenceNo = self.sequenceNo + 1
                reply = None
            elif message[:1] == b'\x03':
                logging.info("Received keep alive while waiting on signatures")
                reply = b"\x04"
            return reply