Esempio n. 1
0
def FiftyTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Transactions/Fifty.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Create and execute a Liver/Syncer.
    Liver(rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"])).live()
    Syncer(rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"])).sync()
Esempio n. 2
0
def HundredTwoTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Consensus/Verification/HundredTwo.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

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

    #Verifies the Transaction is added, it has the right holders, the holders Merit surpasses the threshold, yet it isn't verified.
    def verify() -> None:
        for tx in transactions.txs:
            status: Dict[str, Any] = rpc.call("consensus", "getStatus", [tx.hex()])
            if set(status["verifiers"]) != set([0, 1]):
                raise TestError("Meros doesn't have the right list of verifiers for this Transaction.")

            if status["merit"] != 80:
                raise TestError("Meros doesn't have the right amount of Merit for this Transaction.")

            if rpc.call("merit", "getMerit", [0])["merit"] + rpc.call("merit", "getMerit", [1])["merit"] < status["threshold"]:
                raise TestError("Merit sum of holders is less than the threshold.")

            if status["verified"]:
                raise TestError("Meros verified the Transaction which won't have enough Merit by the time the Transaction finalizes.")

    #Create and execute a Liver.
    Liver(rpc, vectors["blockchain"], transactions, callbacks={100: verify}).live()
Esempio n. 3
0
def VCompetingTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/Verification/Competing.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK", 60,
        int(
            "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            16), vectors["blockchain"])
    #Consensus.
    consensus: Consensus = Consensus.fromJSON(
        bytes.fromhex(
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        ),
        bytes.fromhex(
            "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
        ), vectors["consensus"])
    #Transactions.
    transactions: Transactions = Transactions.fromJSON(vectors["transactions"])

    #Create and execute a Liver/Syncer.
    Liver(rpc, blockchain, consensus, transactions).live()
    Syncer(rpc, blockchain, consensus, transactions).sync()
def InvalidCompetingTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Consensus/MeritRemoval/InvalidCompeting.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    keys: Dict[bytes, int] = {
        bytes.fromhex(vectors["blockchain"][0]["header"]["miner"]): 0
    }

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

    #MeritRemoval.
    #pylint: disable=no-member
    removal: SignedMeritRemoval = SignedMeritRemoval.fromSignedJSON(keys, vectors["removal"])

    #Create and execute a Liver to handle the MeritRemoval.
    def sendMeritRemoval() -> None:
        #Send and verify the MeritRemoval.
        removalBytes: bytes = rpc.meros.signedElement(removal)

        done: bool = False
        while True:
            try:
                msg: bytes = rpc.meros.recv()
            except TestError:
                raise TestError("Node disconnected us.")

            if MessageType(msg[0]) == MessageType.Syncing:
                rpc.meros.syncingAcknowledged()
            elif MessageType(msg[0]) == MessageType.TransactionRequest:
                rpc.meros.transaction(transactions.txs[msg[1 : 33]])
            elif MessageType(msg[0]) == MessageType.SyncingOver:
                if done:
                    break
                done = True

        if removalBytes != rpc.meros.recv():
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 11, 11, removal.holder, True)

    Liver(
        rpc,
        vectors["blockchain"],
        transactions,
        callbacks={
            11: sendMeritRemoval,
            12: lambda: verifyMeritRemoval(rpc, 11, 11, removal.holder, False)
        }
    ).live()

    #Create and execute a Syncer to handle the MeritRemoval.
    Syncer(rpc, vectors["blockchain"], transactions).sync()
    verifyMeritRemoval(rpc, 11, 11, removal.holder, False)
def InvalidCompetingTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/MeritRemoval/InvalidCompeting.json",
        "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

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

    #MeritRemoval.
    #pylint: disable=no-member
    removal: SignedMeritRemoval = SignedMeritRemoval.fromSignedJSON(
        vectors["removal"])

    #Create and execute a Liver to handle the MeritRemoval.
    def sendMeritRemoval() -> None:
        #Send and verify the MeritRemoval.
        removalBytes: bytes = rpc.meros.signedElement(removal)

        sent: int = 0
        while True:
            if sent == 2:
                break

            msg: bytes = rpc.meros.sync.recv()
            if MessageType(msg[0]) == MessageType.TransactionRequest:
                rpc.meros.syncTransaction(transactions.txs[msg[1:33]])
                sent += 1
            else:
                raise TestError("Unexpected message sent: " +
                                msg.hex().upper())

        if removalBytes != rpc.meros.live.recv():
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 1, 1, removal.holder, True)

    #Verify the MeritRemoval and the Blockchain.
    def verify() -> None:
        verifyMeritRemoval(rpc, 1, 1, removal.holder, False)
        verifyBlockchain(rpc, Blockchain.fromJSON(vectors["blockchain"]))
        raise SuccessError(
            "MeritRemoval and Blockchain were properly handled.")

    Liver(rpc,
          vectors["blockchain"],
          transactions,
          callbacks={
              1: sendMeritRemoval,
              2: verify
          }).live()
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()
Esempio n. 7
0
def HundredFortyTwoTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/Verification/HundredFortyTwo.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

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

    #Function to verify the Transaction includes unarchived Merit before finalization.
    def verifyUnarchivedMerit() -> None:
        #Send the verification which won't be archived.
        if rpc.meros.signedElement(
                SignedVerification.fromSignedJSON(
                    vectors["verification"])) != rpc.meros.live.recv():
            raise TestError("Meros didn't send back the SignedVerification.")

        status: Dict[str, Any] = rpc.call("consensus", "getStatus",
                                          [vectors["transaction"]])
        if sorted(status["verifiers"]) != [0, 1]:
            raise TestError(
                "Status didn't include verifiers which have yet to be archived."
            )
        if status["merit"] != 7:
            raise TestError(
                "Status didn't include Merit which has yet to be archived.")

    #Function to verify the Transaction doesn't include unarchived Merit after finalization.
    def verifyArchivedMerit() -> None:
        status: Dict[str, Any] = rpc.call("consensus", "getStatus",
                                          [vectors["transaction"]])
        if status["verifiers"] != [0]:
            raise TestError(
                "Status included verifiers which were never archived.")
        if status["merit"] != 1:
            raise TestError("Status included Merit which was never archived.")

    #Create and execute a Liver.
    Liver(rpc,
          vectors["blockchain"],
          transactions,
          callbacks={
              7: verifyUnarchivedMerit,
              8: verifyArchivedMerit
          }).live()
Esempio n. 8
0
from PythonTests.Classes.Merit.Blockchain import Blockchain

#Ed25519 lib.
import ed25519

#Blake2b standard function.
from hashlib import blake2b

#JSON standard lib.
import json

cmFile: IO[Any] = open("PythonTests/Vectors/Transactions/ClaimedMint.json",
                       "r")
cmVectors: Dict[str, Any] = json.loads(cmFile.read())
#Transactions.
transactions: Transactions = Transactions.fromJSON(cmVectors["transactions"])
#Blockchain.
blockchain: Blockchain = Blockchain.fromJSON(cmVectors["blockchain"])
cmFile.close()

#SpamFilter.
sendFilter: SpamFilter = SpamFilter(3)

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

#BLS keys.
blsPrivKey: PrivateKey = PrivateKey(blake2b(b'\0', digest_size=32).digest())
blsPubKey: PublicKey = blsPrivKey.toPublicKey()
Esempio n. 9
0
def SameInputTest(rpc: RPC) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Transactions/SameInput.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[13]

        #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 an invalid Transaction."
                    )
                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:
                reqHash = msg[1:33]

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

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

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

    #Create and execute a Liver.
    Liver(rpc, vectors["blockchain"], transactions, callbacks={
        12: checkFail
    }).live()
def HundredSixBlockElementsTest(rpc: RPC) -> None:
    #Load the vectors.
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/HundredSix/BlockElements.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain. Solely used to get the genesis Block hash.
    blockchain: Blockchain = Blockchain()

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

    #Parse the Blocks from the vectors.
    blocks: List[Block] = []
    for block in vectors["blocks"]:
        blocks.append(Block.fromJSON({}, block))

    for block in blocks:
        #Handshake with the node.
        rpc.meros.connect(254, 254, blockchain.blocks[0].header.hash)

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

        #Flag of if the Block's Body synced.
        blockBodySynced: bool = False

        #Handle sync requests.
        reqHash: bytes = bytes()
        while True:
            try:
                msg: bytes = rpc.meros.recv()
            except TestError:
                if not blockBodySynced:
                    raise TestError(
                        "Node disconnected us before syncing the body.")

                #Verify the node didn't crash.
                try:
                    if rpc.call("merit", "getHeight") != 1:
                        raise Exception()
                except Exception:
                    raise TestError(
                        "Node crashed after being sent a malformed Element.")

                #Since the node didn't crash, break out of this loop to trigger the next test case.
                break

            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.
                blockBodySynced = True
                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:
                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])

            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 Block with an invalid holder.")

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

        #Reset the node.
        rpc.reset()