Пример #1
0
def ChainAdvancementTest(rpc: RPC) -> None:
    #Blockchain.
    blockchain: Blockchain = Blockchain(
        b"MEROS_DEVELOPER_NETWORK", 60,
        int(
            "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            16))
    #Blocks.
    file: IO[Any] = open("python_tests/Vectors/Merit/BlankBlocks.json", "r")
    blocks: List[Dict[str, Any]] = json.loads(file.read())
    file.close()

    #Publish Blocks.
    for jsonBlock in blocks:
        #Parse the Block.
        block: Block = Block.fromJSON(jsonBlock)

        #Add it locally.
        blockchain.add(block)

        #Publish it.
        rpc.call("merit", "publishBlock", [block.serialize().hex()])

        #Verify the difficulty.
        if int(rpc.call("merit", "getDifficulty"),
               16) != blockchain.difficulty:
            raise TestError("Difficulty doesn't match.")

    #Verify the Blockchain.
    verifyBlockchain(rpc, blockchain)
Пример #2
0
def verifyBlockchain(rpc: RPC, blockchain: Blockchain) -> None:
    #Verify the height.
    if rpc.call("merit", "getHeight") != len(blockchain.blocks):
        raise TestError("Height doesn't match.")

    #Verify the difficulty.
    if blockchain.difficulty != int(rpc.call("merit", "getDifficulty"), 16):
        raise TestError("Difficulty doesn't match.")

    #Verify the blocks.
    for block in blockchain.blocks:
        if rpc.call("merit", "getBlock",
                    [block.header.nonce]) != block.toJSON():
            raise TestError("Block doesn't match.")
Пример #3
0
def verifyConsensus(rpc: RPC, consensus: Consensus) -> None:
    for pubKey in consensus.holders:
        for e in range(len(consensus.holders[pubKey])):
            if rpc.call(
                    "consensus", "getElement",
                [pubKey.hex(), e]) != consensus.holders[pubKey][e].toJSON():
                raise TestError("Element doesn't match.")
Пример #4
0
def verifyMeritRemoval(rpc: RPC, height: int, merit: int,
                       removal: MeritRemoval, pending: bool) -> None:
    #Verify the Merit Holder height.
    if rpc.call("consensus", "getHeight", [removal.holder.hex()]) != height:
        raise TestError("Merit Holder height doesn't match.")

    #Get the MeritRemoval.
    mrJSON: Dict[str, Any] = rpc.call("consensus", "getElement",
                                      [removal.holder.hex(), removal.nonce])

    #Verify the nonce.
    if pending:
        if mrJSON["nonce"] != 0:
            raise TestError("MeritRemoval nonce is invalid.")
        mrJSON["nonce"] = removal.nonce

    #Verify the MeritRemoval.
    if mrJSON != removal.toJSON():
        raise TestError("Merit Removal doesn't match.")

    #Verify the Total Merit.
    if rpc.call("merit", "getTotalMerit") != merit if pending else 0:
        raise TestError("Total Merit doesn't match.")

    #Verify the Live Merit.
    if rpc.call("merit", "getLiveMerit",
                [removal.holder.hex()]) != merit if pending else 0:
        raise TestError("Live Merit doesn't match.")

    #Verify the Merit Holder's Merit.
    if rpc.call("merit", "getMerit", [removal.holder.hex()]) != {
            "live": True,
            "malicious": pending,
            "merit": merit if pending else 0
    }:
        raise TestError("Merit Holder's Merit doesn't match.")
Пример #5
0
def MRPALiveTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "python_tests/Vectors/Consensus/MeritRemoval/PendingActions.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    #Datas.
    datas: List[Data] = []
    for data in vectors["datas"]:
        datas.append(Data.fromJSON(data))
    #SignedVerifications.
    verifs: List[SignedVerification] = []
    for verif in vectors["verifications"]:
        verifs.append(SignedVerification.fromJSON(verif))
    #Removal.
    removal: SignedMeritRemoval = SignedMeritRemoval.fromJSON(
        vectors["removal"])
    #Consensus.
    consensus: Consensus = Consensus(
        bytes.fromhex(
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        ),
        bytes.fromhex(
            "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
        ),
    )
    consensus.add(verifs[0])
    consensus.add(verifs[1])
    consensus.add(verifs[2])
    consensus.add(removal)
    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK", 60,
        int(
            "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            16), vectors["blockchain"])
    file.close()

    #Handshake with the node.
    rpc.meros.connect(254, 254, len(blockchain.blocks) - 2)

    hash: bytes = bytes()
    msg: bytes = bytes()
    height: int = 0
    while True:
        msg = rpc.meros.recv()

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

        elif MessageType(msg[0]) == MessageType.GetBlockHash:
            height = int.from_bytes(msg[1:5], byteorder="big")
            if height == 0:
                rpc.meros.blockHash(blockchain.blocks[1].header.hash)
            else:
                if height >= len(blockchain.blocks):
                    raise TestError(
                        "Meros asked for a Block Hash we do not have.")

                rpc.meros.blockHash(blockchain.blocks[height].header.hash)

        elif MessageType(msg[0]) == MessageType.BlockHeaderRequest:
            hash = msg[1:49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockHeader(block.header)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError(
                        "Meros asked for a Block Header we do not have.")

        elif MessageType(msg[0]) == MessageType.BlockBodyRequest:
            hash = msg[1:49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockBody(block.body)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError(
                        "Meros asked for a Block Body we do not have.")

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

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

    #Send the Datas.
    for data in datas:
        if rpc.meros.transaction(data) != rpc.meros.recv():
            raise TestError("Unexpected message sent.")

    #Send the Verifications.
    for verif in verifs:
        if rpc.meros.signedElement(verif) != rpc.meros.recv():
            raise TestError("Unexpected message sent.")

    #Verify every Data has 100 Merit.
    for data in datas:
        if rpc.call("transactions", "getMerit", [data.hash.hex()]) != {
                "merit": 100
        }:
            raise TestError(
                "Meros didn't verify Transactions with received Verifications."
            )

    #Send and verify the MeritRemoval.
    if rpc.meros.signedElement(removal) != rpc.meros.recv():
        raise TestError("Meros didn't send us the Merit Removal.")
    verifyMeritRemoval(rpc, 1, 100, removal, True)

    #Verify every Data has 100 Merit.
    for data in datas:
        if rpc.call("transactions", "getMerit", [data.hash.hex()]) != {
                "merit": 0
        }:
            raise TestError(
                "Meros didn't revert pending actions of a malicious MeritHolder."
            )

    #Send the next Block.
    rpc.meros.blockHeader(blockchain.blocks[-2].header)
    while True:
        msg = rpc.meros.recv()

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

        elif MessageType(msg[0]) == MessageType.GetBlockHash:
            height = int.from_bytes(msg[1:5], byteorder="big")
            if height == 0:
                rpc.meros.blockHash(blockchain.last())
            else:
                if height >= len(blockchain.blocks):
                    raise TestError(
                        "Meros asked for a Block Hash we do not have.")

                rpc.meros.blockHash(blockchain.blocks[height].header.hash)

        elif MessageType(msg[0]) == MessageType.BlockHeaderRequest:
            hash = msg[1:49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockHeader(block.header)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError(
                        "Meros asked for a Block Header we do not have.")

        elif MessageType(msg[0]) == MessageType.BlockBodyRequest:
            hash = msg[1:49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockBody(block.body)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError(
                        "Meros asked for a Block Body we do not have.")

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

        elif MessageType(msg[0]) == MessageType.BlockHeader:
            break

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

    #Update the MeritRemoval's nonce.
    removal.nonce = 3

    #Verify the Datas have the Merit they should.
    for d in range(len(datas)):
        if rpc.call("transactions", "getMerit", [datas[d].hash.hex()]) != {
                "merit": 100 if d < 3 else 0
        }:
            raise TestError(
                "Meros didn't apply reverted pending actions of a malicious MeritHolder."
            )

    #Verify the MeritRemoval is now accessible with a nonce of 3.
    verifyMeritRemoval(rpc, 4, 200, removal, True)

    #Archive the MeritRemoval.
    rpc.meros.blockHeader(blockchain.blocks[-1].header)
    while True:
        msg = rpc.meros.recv()

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

        elif MessageType(msg[0]) == MessageType.GetBlockHash:
            height = int.from_bytes(msg[1:5], byteorder="big")
            if height == 0:
                rpc.meros.blockHash(blockchain.last())
            else:
                if height >= len(blockchain.blocks):
                    raise TestError(
                        "Meros asked for a Block Hash we do not have.")

                rpc.meros.blockHash(blockchain.blocks[height].header.hash)

        elif MessageType(msg[0]) == MessageType.BlockHeaderRequest:
            hash = msg[1:49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockHeader(block.header)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError(
                        "Meros asked for a Block Header we do not have.")

        elif MessageType(msg[0]) == MessageType.BlockBodyRequest:
            hash = msg[1:49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockBody(block.body)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError(
                        "Meros asked for a Block Body we do not have.")

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

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

    #Verify the Blockchain.
    verifyBlockchain(rpc, blockchain)

    #Verify the Consensus.
    verifyConsensus(rpc, consensus)

    #Verify the MeritRemoval again.
    verifyMeritRemoval(rpc, 4, 200, removal, False)
Пример #6
0
def VUnknown(
    rpc: RPC
) -> None:
    file: IO[Any] = open("python_tests/Vectors/Consensus/Verification/Parsable.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    #SignedVerification.
    sv: SignedVerification = SignedVerification.fromJSON(vectors["verification"])
    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK",
        60,
        int("FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 16),
        vectors["blockchain"]
    )
    file.close()

    #Handshake with the node.
    rpc.meros.connect(
        254,
        254,
        len(blockchain.blocks)
    )

    sentLast: bool = False
    hash: bytes = bytes()
    while True:
        msg: bytes = rpc.meros.recv()

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

        elif MessageType(msg[0]) == MessageType.GetBlockHash:
            height: int = int.from_bytes(msg[1 : 5], byteorder = "big")
            if height == 0:
                rpc.meros.blockHash(blockchain.last())
            else:
                if height >= len(blockchain.blocks):
                    raise TestError("Meros asked for a Block Hash we do not have.")

                rpc.meros.blockHash(blockchain.blocks[height].header.hash)

        elif MessageType(msg[0]) == MessageType.BlockHeaderRequest:
            hash = msg[1 : 49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockHeader(block.header)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError("Meros asked for a Block Header we do not have.")

        elif MessageType(msg[0]) == MessageType.BlockBodyRequest:
            hash = msg[1 : 49]
            for block in blockchain.blocks:
                if block.header.hash == hash:
                    rpc.meros.blockBody(block.body)
                    break

                if block.header.hash == blockchain.last():
                    raise TestError("Meros asked for a Block Body we do not have.")

        elif MessageType(msg[0]) == MessageType.ElementRequest:
            rpc.meros.element(sv)

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

        elif MessageType(msg[0]) == MessageType.SyncingOver:
            if sentLast:
                break

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

    #Verify the Verification and Block were not added.
    if rpc.call("consensus", "getHeight", [sv.holder.hex()]) != 0:
        raise TestError("Meros added an unknown Verification.")

    if rpc.call("merit", "getHeight") != 2:
        raise TestError("Meros added a block with an unknown Verification.")
Пример #7
0
    pass

#Run every test.
for test in tests:
    if len(testsToRun) == 0:
        break
    if test.__name__ not in testsToRun:
        continue
    testsToRun.remove(test.__name__)

    print("Running " + test.__name__ + ".")

    meros: Meros = Meros(test.__name__, port, port + 1)
    sleep(2)

    rpc: RPC = RPC(meros)
    try:
        test(rpc)
        ress.append("\033[0;32m" + test.__name__ + " succeeded.")
    except EmptyError as e:
        ress.append("\033[0;33m" + test.__name__ + " is empty.")
        continue
    except NodeError as e:
        ress.append("\033[5;31m" + test.__name__ +
                    " caused the node to crash!\033[0;31m")
    except TestError as e:
        ress.append("\033[0;31m" + test.__name__ + " failed: " + str(e))
        continue
    except Exception as e:
        ress.append("\r\n")
        ress.append("\033[0;31m" + test.__name__ + " is invalid.")
Пример #8
0
def verifyTransaction(rpc: RPC, tx: Transaction) -> None:
    if rpc.call("transactions", "getTransaction",
                [tx.hash.hex()]) != tx.toJSON():
        raise TestError("Transaction doesn't match.")