Ejemplo n.º 1
0
def HundredTest(rpc: RPC) -> None:
    #Blocks.
    file: IO[Any] = open("PythonTests/Vectors/Merit/BlankBlocks.json", "r")
    blocks: List[Dict[str, Any]] = json.loads(file.read())
    file.close()

    #Grab only the first block.
    blocks = [blocks[0]]

    #Merit.
    merit: Merit = Merit.fromJSON(blocks)

    #The normal flow would be:
    #Handshake
    #BlockHeaderRequest

    #We need to delay the BlockHeader. Then, Meros should send:
    #Handshake
    #BlockHeaderRequest
    #Handshake

    #EXCEPT Meros can't handle sending Handshakes after Requests like that (see issue #100).
    #Therefore, Meros won't send a Handshake if it has a pending request (totally valid and acceptable behavior).
    #This test verifies we get disconnected without a Handshake attempt.

    #Handshake with the node.
    rpc.meros.connect(254, 254, merit.blockchain.blocks[1].header.hash)

    #Handle sync requests.
    reqHash: bytes = bytes()
    while True:
        msg: bytes = rpc.meros.recv()

        if MessageType(msg[0]) == MessageType.Syncing:
            rpc.meros.syncingAcknowledged()

        elif MessageType(msg[0]) == MessageType.BlockHeaderRequest:
            reqHash = msg[1:33]
            if reqHash != merit.blockchain.blocks[-1].header.hash:
                raise TestError(
                    "Meros asked for a BlockHeader other than the one in the Block from the Handshake."
                )

            #Wait until Meros disconnects us.
            try:
                rpc.meros.recv()
            except TestError:
                raise SuccessError(
                    "Meros didn't attempt to handshake with us while it had a pending sync request."
                )
            raise TestError(
                "Meros tried to handshake with us while it had a pending sync request."
            )
Ejemplo n.º 2
0
    def __init__(self,
                 rpc: RPC,
                 blockchain: List[Dict[str, Any]],
                 transactions: Optional[Transactions] = None,
                 callbacks: Dict[int, Callable[[], None]] = {},
                 everyBlock: Optional[Callable[[int], None]] = None) -> None:
        #RPC.
        self.rpc: RPC = rpc

        #Arguments.
        self.merit: Merit = Merit.fromJSON(blockchain)
        self.transactions: Optional[Transactions] = transactions

        self.callbacks: Dict[int, Callable[[], None]] = dict(callbacks)
        self.everyBlock: Optional[Callable[[int], None]] = everyBlock
Ejemplo n.º 3
0
def HundredFortySevenTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Transactions/ClaimedMint.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Merit.
    merit: Merit = Merit.fromJSON(vectors["blockchain"])
    #Transactions.
    transactions: Transactions = Transactions.fromJSON(vectors["transactions"])

    #Ed25519 keys.
    privKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
    pubKey: ed25519.VerifyingKey = privKey.get_verifying_key()

    #Grab the Claim hash,
    claim: bytes = merit.blockchain.blocks[-1].body.packets[0].hash

    #Create a Send which underflows.
    send: Send = Send(
        [(claim, 0)],
        [
            (pubKey.to_bytes(), 18446744073709551231),
            (pubKey.to_bytes(), 385 + Claim.fromTransaction(transactions.txs[claim]).amount)
        ]
    )
    send.sign(privKey)
    send.beat(SpamFilter(3))

    #Custom function to send the last Block and verify it errors at the right place.
    def checkFail() -> None:
        #Send the Send.
        rpc.meros.liveTransaction(send)

        #Handle sync requests.
        while True:
            #Try receiving from the Live socket, where Meros sends keep-alives.
            try:
                if len(rpc.meros.live.recv()) != 0:
                    raise Exception()
            except TestError:
                raise SuccessError("Node disconnected us after we sent an invalid Transaction.")
            except Exception:
                raise TestError("Meros sent a keep-alive.")

    #Create and execute a Liver.
    Liver(rpc, vectors["blockchain"], transactions, callbacks={12: checkFail}).live()
Ejemplo n.º 4
0
    def __init__(self,
                 rpc: RPC,
                 blockchain: List[Dict[str, Any]],
                 transactions: Union[Transactions, None] = None,
                 settings: Dict[str, Any] = {}) -> None:
        #RPC.
        self.rpc: RPC = rpc

        #DBs/Settings.
        self.merit: Merit = Merit.fromJSON(blockchain)
        self.transactions: Union[Transactions, None] = transactions
        self.settings: Dict[str, Any] = dict(settings)

        #Provide default settings.
        if "height" not in self.settings:
            self.settings["height"] = len(self.merit.blockchain.blocks) - 1
        if "playback" not in self.settings:
            self.settings["playback"] = True

        #List of Block hashes in this Blockchain.
        self.blockHashes: Set[bytes] = set()
        for b in range(1, self.settings["height"] + 1):
            self.blockHashes.add(self.merit.blockchain.blocks[b].header.hash)

        #List of mentioned Blocks.
        self.blocks: List[Block] = [
            self.merit.blockchain.blocks[self.settings["height"]]
        ]

        #Dict of mentioned packets.
        self.packets: Dict[int, VerificationPacket] = {}

        #Set of mentioned Transactions.
        self.txs: Set[bytes] = set()
        #Dict of synced Transactions.
        self.synced: Set[bytes] = set()
Ejemplo n.º 5
0
def VUnknownTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/Verification/Parsable.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Merit.
    merit: Merit = Merit.fromJSON(vectors["blockchain"])

    #Custom function to send the last Block and verify it errors at the right place.
    def checkFail() -> None:
        #This Block should cause the node to disconnect us AFTER it attempts to sync our Transaction.
        syncedTX: bool = False

        #Grab the Block.
        block: Block = merit.blockchain.blocks[2]

        #Send the Block.
        rpc.meros.liveBlockHeader(block.header)

        #Handle sync requests.
        reqHash: bytes = bytes()
        while True:
            if syncedTX:
                #Try receiving from the Live socket, where Meros sends keep-alives.
                try:
                    if len(rpc.meros.live.recv()) != 0:
                        raise Exception()
                except TestError:
                    raise SuccessError(
                        "Node disconnected us after we sent a parsable, yet invalid, Verification."
                    )
                except Exception:
                    raise TestError("Meros sent a keep-alive.")

            msg: bytes = rpc.meros.sync.recv()
            if MessageType(msg[0]) == MessageType.BlockBodyRequest:
                reqHash = msg[1:33]
                if reqHash != block.header.hash:
                    raise TestError(
                        "Meros asked for a Block Body that didn't belong to the Block we just sent it."
                    )

                #Send the BlockBody.
                rpc.meros.blockBody(block)

            elif MessageType(msg[0]) == MessageType.SketchHashesRequest:
                if not block.body.packets:
                    raise TestError(
                        "Meros asked for Sketch Hashes from a Block without any."
                    )

                reqHash = msg[1:33]
                if reqHash != block.header.hash:
                    raise TestError(
                        "Meros asked for Sketch Hashes that didn't belong to the Block we just sent it."
                    )

                #Create the haashes.
                hashes: List[int] = []
                for packet in block.body.packets:
                    hashes.append(Sketch.hash(block.header.sketchSalt, packet))

                #Send the Sketch Hashes.
                rpc.meros.sketchHashes(hashes)

            elif MessageType(msg[0]) == MessageType.SketchHashRequests:
                if not block.body.packets:
                    raise TestError(
                        "Meros asked for Verification Packets from a Block without any."
                    )

                reqHash = msg[1:33]
                if reqHash != block.header.hash:
                    raise TestError(
                        "Meros asked for Verification Packets that didn't belong to the Block we just sent it."
                    )

                #Create a lookup of hash to packets.
                packets: Dict[int, VerificationPacket] = {}
                for packet in block.body.packets:
                    packets[Sketch.hash(block.header.sketchSalt,
                                        packet)] = packet

                #Look up each requested packet and respond accordingly.
                for h in range(int.from_bytes(msg[33:37], byteorder="big")):
                    sketchHash: int = int.from_bytes(msg[37 + (h * 8):45 +
                                                         (h * 8)],
                                                     byteorder="big")
                    if sketchHash not in packets:
                        raise TestError(
                            "Meros asked for a non-existent Sketch Hash.")
                    rpc.meros.packet(packets[sketchHash])

            elif MessageType(msg[0]) == MessageType.TransactionRequest:
                rpc.meros.dataMissing()
                syncedTX = True

            else:
                raise TestError("Unexpected message sent: " +
                                msg.hex().upper())

    #Create and execute a Liver.
    Liver(rpc, vectors["blockchain"], callbacks={1: checkFail}).live()
Ejemplo n.º 6
0
def CompetingFinalizedTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Transactions/CompetingFinalized.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Merit.
    merit: Merit = Merit.fromJSON(vectors["blockchain"])
    #Transactions.
    transactions: Transactions = Transactions.fromJSON(vectors["transactions"])

    #Custom function to send the last Block and verify it errors at the right place.
    def checkFail() -> None:
        #This Block should cause the node to disconnect us AFTER it syncs our Transaction.
        syncedTX: bool = False

        #Grab the Block.
        block: Block = merit.blockchain.blocks[-1]

        #Send the Block.
        rpc.meros.blockHeader(block.header)

        #Handle sync requests.
        reqHash: bytes = bytes()
        while True:
            try:
                msg: bytes = rpc.meros.recv()
            except TestError:
                if syncedTX:
                    raise SuccessError("Node disconnected us after we sent an invalid Transaction.")
                raise TestError("Node errored before syncing our Transaction.")

            if MessageType(msg[0]) == MessageType.Syncing:
                rpc.meros.syncingAcknowledged()

            elif MessageType(msg[0]) == MessageType.BlockBodyRequest:
                reqHash = msg[1 : 33]
                if reqHash != block.header.hash:
                    raise TestError("Meros asked for a Block Body that didn't belong to the Block we just sent it.")

                #Send the BlockBody.
                rpc.meros.blockBody(merit.state.nicks, block)

            elif MessageType(msg[0]) == MessageType.SketchHashesRequest:
                if not block.body.packets:
                    raise TestError("Meros asked for Sketch Hashes from a Block without any.")

                reqHash = msg[1 : 33]
                if reqHash != block.header.hash:
                    raise TestError("Meros asked for Sketch Hashes that didn't belong to the Block we just sent it.")

                #Create the haashes.
                hashes: List[int] = []
                for packet in block.body.packets:
                    hashes.append(Sketch.hash(block.header.sketchSalt, packet))

                #Send the Sketch Hashes.
                rpc.meros.sketchHashes(hashes)

            elif MessageType(msg[0]) == MessageType.SketchHashRequests:
                if not block.body.packets:
                    raise TestError("Meros asked for Verification Packets from a Block without any.")

                reqHash = msg[1 : 33]
                if reqHash != block.header.hash:
                    raise TestError("Meros asked for Verification Packets that didn't belong to the Block we just sent it.")

                #Create a lookup of hash to packets.
                packets: Dict[int, VerificationPacket] = {}
                for packet in block.body.packets:
                    packets[Sketch.hash(block.header.sketchSalt, packet)] = packet

                #Look up each requested packet and respond accordingly.
                for h in range(int.from_bytes(msg[33 : 37], byteorder="big")):
                    sketchHash: int = int.from_bytes(msg[37 + (h * 8) : 45 + (h * 8)], byteorder="big")
                    if sketchHash not in packets:
                        raise TestError("Meros asked for a non-existent Sketch Hash.")
                    rpc.meros.packet(packets[sketchHash])

            elif MessageType(msg[0]) == MessageType.TransactionRequest:
                reqHash = msg[1 : 33]

                if reqHash not in transactions.txs:
                    raise TestError("Meros asked for a non-existent Transaction.")

                rpc.meros.transaction(transactions.txs[reqHash])
                syncedTX = True

            elif MessageType(msg[0]) == MessageType.SyncingOver:
                pass

            elif MessageType(msg[0]) == MessageType.BlockHeader:
                #Raise a TestError if the Block was added.
                raise TestError("Meros synced a Transaction which competed with a finalized Transaction.")

            else:
                raise TestError("Unexpected message sent: " + msg.hex().upper())

    #Create and execute a Liver.
    Liver(rpc, vectors["blockchain"], transactions, callbacks={7: checkFail}).live()