Beispiel #1
0
    def test() -> None:
        recipient: ed25519.SigningKey = ed25519.SigningKey(b'\1' * 32)
        recipientPub: bytes = recipient.get_verifying_key().to_bytes()
        address: str = bech32_encode(
            "mr", convertbits(bytes([0]) + recipientPub, 8, 5))

        otherRecipient: bytes = ed25519.SigningKey(
            b'\2' * 32).get_verifying_key().to_bytes()
        otherAddress: str = bech32_encode(
            "mr", convertbits(bytes([0]) + otherRecipient, 8, 5))

        #Create a Send.
        send: Send = Send.fromJSON(vectors["send"])
        if rpc.meros.liveTransaction(send) != rpc.meros.live.recv():
            raise TestError("Meros didn't broadcast back a Send.")
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros considered an unconfirmed Transaction's outputs as UTXOs."
            )
        verify(rpc, send.hash)

        #Spend it.
        spendingSend: Send = Send.fromJSON(vectors["spendingSend"])
        if rpc.meros.liveTransaction(spendingSend) != rpc.meros.live.recv():
            raise TestError("Meros didn't broadcast back a Send.")
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros didn't consider a Transaction's inputs as spent.")

        #Verify with another party, so it won't be majority verified, yet will still have a Verification.
        mineBlock(rpc, 1)
        verify(rpc, spendingSend.hash, 1)
        #Verify it didn't create a UTXO.
        if rpc.call("transactions", "getUTXOs",
                    {"address": otherAddress}) != []:
            raise TestError("Unverified Transaction created a UTXO.")

        #Finalize.
        for _ in range(6):
            mineBlock(rpc)

        #Check the UTXOs were created.
        if rpc.call("transactions", "getUTXOs", {"address": otherAddress}) != [
            {
                "hash": spendingSend.hash.hex().upper(),
                "nonce": 0
            }
        ]:
            raise TestError(
                "Meros didn't consider a finalized Transaction's outputs as UTXOs."
            )

        raise SuccessError()
Beispiel #2
0
def ImpossibleFamilyTest(
  rpc: RPC
) -> None:
  vectors: Dict[str, Any]
  with open("e2e/Vectors/Consensus/Families/ImpossibleFamily.json", "r") as file:
    vectors = json.loads(file.read())
  sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]]

  def sendSends() -> None:
    for s in range(len(sends)):
      if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv():
        raise TestError("Meros didn't broadcast a Send.")

  def verifyPossibleWon() -> None:
    if rpc.call("consensus", "getStatus", [sends[1].hash.hex()])["verified"]:
      raise TestError("Meros verified an impossible Transaction.")
    if not rpc.call("consensus", "getStatus", [sends[0].hash.hex()])["verified"]:
      raise TestError("Meros didn't verify the only possible Transaction.")

  Liver(
    rpc,
    vectors["blockchain"],
    Transactions.fromJSON(vectors["transactions"]),
    callbacks={
      42: sendSends,
      48: verifyPossibleWon
    }
  ).live()
Beispiel #3
0
def DescendantHighestUnverifiedParentTest(rpc: RPC) -> None:
    vectors: Dict[str, Any]
    with open(
            "e2e/Vectors/Consensus/Families/DescendantHighestUnverifiedParent.json",
            "r") as file:
        vectors = json.loads(file.read())
    sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]]

    def sendSends() -> None:
        for s in range(len(sends)):
            if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv():
                raise TestError("Meros didn't broadcast a Send.")

    def verifyDescendantLost() -> None:
        for send in sends[1:]:
            if rpc.call("consensus", "getStatus",
                        {"hash": send.hash.hex()})["verified"]:
                raise TestError(
                    "Meros verified a beaten transaction or one of its children (one of which is impossible)."
                )
        if not rpc.call("consensus", "getStatus",
                        {"hash": sends[0].hash.hex()})["verified"]:
            raise TestError(
                "Meros either didn't verify the descendant or its parent.")

    Liver(rpc,
          vectors["blockchain"],
          Transactions.fromJSON(vectors["transactions"]),
          callbacks={
              45: sendSends,
              51: verifyDescendantLost
          }).live()
def UnionedFamiliesSingleWinnerTest(
  rpc: RPC
) -> None:
  vectors: Dict[str, Any]
  with open("e2e/Vectors/Consensus/Families/UnionedFamiliesSingleWinner.json", "r") as file:
    vectors = json.loads(file.read())
  sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]]

  def sendSends() -> None:
    for s in range(len(sends)):
      if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv():
        raise TestError("Meros didn't broadcast a Send.")

  def verifyUnionizingWon() -> None:
    for send in sends[:-1]:
      if rpc.call("consensus", "getStatus", {"hash": send.hash.hex()})["verified"]:
        raise TestError("Meros verified a transaction which was beaten by a unionizing transaction.")
    if not rpc.call("consensus", "getStatus", {"hash": sends[-1].hash.hex()})["verified"]:
      raise TestError("Meros didn't verify the verified unionizing transaction.")

  Liver(
    rpc,
    vectors["blockchain"],
    Transactions.fromJSON(vectors["transactions"]),
    callbacks={
      45: sendSends,
      51: verifyUnionizingWon
    }
  ).live()
Beispiel #5
0
def UnionedFamiliesMultipleWinnersTest(rpc: RPC) -> None:
    vectors: Dict[str, Any]
    with open(
            "e2e/Vectors/Consensus/Families/UnionedFamiliesMultipleWinners.json",
            "r") as file:
        vectors = json.loads(file.read())
    sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]]

    def sendSends() -> None:
        for s in range(len(sends)):
            if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv():
                raise TestError("Meros didn't broadcast a Send.")

    def verifyMultipleWon() -> None:
        for send in [sends[1], *sends[3:]]:
            if rpc.call("consensus", "getStatus",
                        [send.hash.hex()])["verified"]:
                raise TestError(
                    "Meros verified a transaction which was beaten by another transaction."
                )
        for send in [sends[0], sends[2]]:
            if not rpc.call("consensus", "getStatus",
                            [send.hash.hex()])["verified"]:
                raise TestError(
                    "Meros didn't verify the verified transaction for each original family."
                )

    Liver(rpc,
          vectors["blockchain"],
          Transactions.fromJSON(vectors["transactions"]),
          callbacks={
              44: sendSends,
              50: verifyMultipleWon
          }).live()
Beispiel #6
0
  def test() -> None:
    recipient: Ristretto.SigningKey = Ristretto.SigningKey(b'\1' * 32)
    recipientPub: bytes = recipient.get_verifying_key()
    address: str = bech32_encode("mr", convertbits(bytes([0]) + recipientPub, 8, 5))

    #Create a Send.
    send: Send = Send.fromJSON(vectors["send"])
    if rpc.meros.liveTransaction(send) != rpc.meros.live.recv():
      raise TestError("Meros didn't broadcast back a Send.")
    verify(rpc, send.hash)
    if rpc.call("transactions", "getUTXOs", {"address": address}) != [{"hash": send.hash.hex().upper(), "nonce": 0}]:
      raise TestError("Meros didn't consider a confirmed Transaction's outputs as UTXOs.")
    #Spend it, with a newer Mint as an input as well so we can prune it without pruning the original.
    newerSend: Send = createSend(rpc, [Claim.fromJSON(vectors["newerMintClaim"])], recipientPub)
    _: Send = createSend(rpc, [send, newerSend], bytes(32), recipient)
    if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
      raise TestError("Meros thinks the recipient has UTXOs.")

    #Remove the spending Send by pruning its ancestor (a Mint).
    reorg(rpc, Blockchain.fromJSON(vectors["blocksWithoutNewerMint"]))
    #Meros should add back its parent as an UTXO.
    if rpc.call("transactions", "getUTXOs", {"address": address}) != [{"hash": send.hash.hex().upper(), "nonce": 0}]:
      raise TestError("Meros didn't consider a Transaction without spenders as an UTXO.")
    #Remove the original Send and verify its outputs are no longer considered UTXOs.
    reorg(rpc, Blockchain.fromJSON(vectors["blocksWithoutOlderMint"]))
    if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
      raise TestError("Meros didn't remove the outputs of a pruned Transaction as UTXOs.")

    raise SuccessError()
Beispiel #7
0
def checkSend(rpc: RPC, sendHash: str, expected: Dict[str, Any]) -> None:
    send: Dict[str, Any] = rpc.call("transactions", "getTransaction",
                                    {"hash": sendHash})
    serialized: bytes = Send.fromJSON(send).serialize()
    del send["signature"]
    del send["proof"]

    expected["descendant"] = "Send"
    expected["hash"] = sendHash
    if sortUTXOs(send["inputs"]) != sortUTXOs(expected["inputs"]):
        raise TestError("Send inputs weren't as expected.")
    del send["inputs"]
    del expected["inputs"]
    if send != expected:
        raise TestError("Send wasn't as expected.")

    if rpc.meros.live.recv() != (MessageType.Send.toByte() + serialized):
        raise TestError("Meros didn't broadcast a Send it created.")
def TGUImmediatelyTest(rpc: RPC) -> None:
    recipient: ed25519.SigningKey = ed25519.SigningKey(b'\1' * 32)
    recipientPub: bytes = recipient.get_verifying_key().to_bytes()
    address: str = bech32_encode("mr",
                                 convertbits(bytes([0]) + recipientPub, 8, 5))

    vectors: Dict[str, Any]
    with open("e2e/Vectors/RPC/Transactions/GetUTXOs.json", "r") as file:
        vectors = json.loads(file.read())
    transactions: Transactions = Transactions.fromJSON(vectors["transactions"])

    send: Send = Send.fromJSON(vectors["send"])
    spendingSend: Send = Send.fromJSON(vectors["spendingSend"])

    def start() -> None:
        #Send the Send.
        if rpc.meros.liveTransaction(send) != rpc.meros.live.recv():
            raise TestError("Meros didn't broadcast back a Send.")
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros considered an unconfirmed Transaction's outputs as UTXOs."
            )

        #Immediately spend it.
        if rpc.meros.liveTransaction(spendingSend) != rpc.meros.live.recv():
            raise TestError("Meros didn't broadcast back a Send.")
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros didn't consider a Transaction's inputs as spent.")

        #Verify the Send and make sure it's not considered as a valid UTXO.
        verify(rpc, send.hash)
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros considered a just confirmed Transaction with a spender's outputs as UTXOs."
            )

    def verified() -> None:
        #Verify the spender and verify the state is unchanged.
        verify(rpc, spendingSend.hash)
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros didn't consider a verified Transaction's inputs as spent."
            )

    def finalizedSend() -> None:
        #Sanity check the spending TX has yet to also finalize.
        if rpc.call("consensus", "getStatus",
                    {"hash": spendingSend.hash.hex()})["finalized"]:
            raise Exception(
                "Test meant to only finalize the first Send, not both.")

        #Verify the state is unchanged.
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros didn't consider a verified Transaction's inputs as spent after the input finalized."
            )

    def finalizedSpendingSend() -> None:
        #Verify the state is unchanged.
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros didn't consider a finalized Transaction's inputs as spent."
            )

    Liver(rpc, vectors["blockchain"], transactions, {
        50: start,
        51: verified,
        56: finalizedSend,
        57: finalizedSpendingSend
    }).live()
Beispiel #9
0
def BeatenTest(rpc: RPC) -> None:
    vectors: Dict[str, Any]
    with open("e2e/Vectors/Consensus/Beaten.json", "r") as file:
        vectors = json.loads(file.read())
    sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]]
    verif: SignedVerification = SignedVerification.fromSignedJSON(
        vectors["verification"])

    #Used to get the Block Template.
    blsPubKey: str = PrivateKey(0).toPublicKey().serialize().hex()

    def sendSends() -> None:
        for send in sends[:4]:
            if rpc.meros.liveTransaction(send) != rpc.meros.live.recv():
                raise TestError("Meros didn't broadcast a Send.")
        if rpc.meros.signedElement(verif) != rpc.meros.live.recv():
            raise TestError("Meros didn't broadcast a Verification.")

    #Sanity check to verify the Block Template contains the Verification.
    def verifyTemplate() -> None:
        if bytes.fromhex(
                rpc.call("merit", "getBlockTemplate",
                         {"miner": blsPubKey
                          })["header"])[36:68] != BlockHeader.createContents(
                              [VerificationPacket(sends[2].hash, [1])]):
            raise TestError(
                "Meros didn't add a SignedVerification to the Block Template.")

    def verifyBeaten() -> None:
        #Verify beaten was set. The fourth Transaction is also beaten, yet should be pruned.
        #That's why we don't check its status.
        for send in sends[1:3]:
            if not rpc.call("consensus", "getStatus",
                            {"hash": send.hash.hex()})["beaten"]:
                raise TestError(
                    "Meros didn't mark a child and its descendant as beaten.")

        #Check the pending Verification for the beaten descendant was deleted.
        if ((rpc.call("consensus", "getStatus",
                      {"hash": sends[2].hash.hex()})["verifiers"] != [0])
                or (bytes.fromhex(
                    rpc.call("merit", "getBlockTemplate",
                             {"miner": blsPubKey})["header"])[36:68] !=
                    bytes(32))):
            raise TestError("Block template still has the Verification.")

        #Verify the fourth Transaction was pruned.
        with raises(TestError):
            rpc.call("transactions", "getTransaction",
                     {"hash": sends[3].hash.hex()})

        #Verify neither the second or third Transaction tree can be appended to.
        #Publishes a never seen-before Send for the descendant.
        #Re-broadcasts the pruned Transaction for the parent.
        for send in sends[3:]:
            #Most of these tests use a socket connection for this.
            #This has identical effects, returns an actual error instead of a disconnect,
            #and doesn't force us to wait a minute for our old socket to be cleared.
            with raises(TestError):
                rpc.call("transactions", "publishTransaction", {
                    "type": "Send",
                    "transaction": send.serialize().hex()
                })

        #Not loaded above as it can only be loqaded after the chain starts, which is done by the Liver.
        #RandomX cache keys and all that.
        blockWBeatenVerif: Block = Block.fromJSON(
            vectors["blockWithBeatenVerification"])

        #The following code used to test behavior which was removed, in order to be more forgiving for nodes a tad behind.

        #Verify we can't add that SignedVerification now.
        #rpc.meros.signedElement(verif)
        #try:
        #  rpc.meros.live.recv()
        #  #Hijacks a random Exception type for our purposes.
        #  raise MessageException("Meros didn't disconnect us after we sent a Verification for a beaten Transaction.")
        #except TestError:
        #  pass
        #except MessageException as e:
        #  raise TestError(e.message)
        #sleep(65)
        #rpc.meros.liveConnect(blockWBeatenVerif.header.last)

        #Verify we can't add a Block containing that Verification.
        rpc.meros.liveBlockHeader(blockWBeatenVerif.header)

        #BlockBody sync request.
        rpc.meros.handleBlockBody(blockWBeatenVerif)

        #Sketch hash sync request.
        hashReqs: bytes = rpc.meros.sync.recv()[37:]
        for h in range(0, len(hashReqs), 8):
            for packet in blockWBeatenVerif.body.packets:
                if int.from_bytes(hashReqs[h:h + 8],
                                  byteorder="little") == Sketch.hash(
                                      blockWBeatenVerif.header.sketchSalt,
                                      packet):
                    rpc.meros.packet(packet)
                    break

        try:
            rpc.meros.live.recv()
            raise MessageException(
                "Meros didn't disconnect us after we sent a Block containing a Verification of a beaten Transaction."
            )
        except TestError:
            pass
        except MessageException as e:
            raise TestError(e.message)

        sleep(65)
        rpc.meros.liveConnect(blockWBeatenVerif.header.last)
        rpc.meros.syncConnect(blockWBeatenVerif.header.last)

    Liver(rpc,
          vectors["blockchain"],
          Transactions.fromJSON(vectors["transactions"]),
          callbacks={
              42: sendSends,
              43: verifyTemplate,
              48: verifyBeaten
          }).live()
Beispiel #10
0
    def test() -> None:
        recipient: ed25519.SigningKey = ed25519.SigningKey(b'\1' * 32)
        recipientPub: bytes = recipient.get_verifying_key().to_bytes()
        address: str = bech32_encode(
            "mr", convertbits(bytes([0]) + recipientPub, 8, 5))

        otherRecipient: bytes = ed25519.SigningKey(
            b'\2' * 32).get_verifying_key().to_bytes()
        otherAddress: str = bech32_encode(
            "mr", convertbits(bytes([0]) + otherRecipient, 8, 5))

        #Create a Send.
        send: Send = Send.fromJSON(vectors["send"])
        if rpc.meros.liveTransaction(send) != rpc.meros.live.recv():
            raise TestError("Meros didn't broadcast back a Send.")
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros considered an unconfirmed Transaction's outputs as UTXOs."
            )
        verify(rpc, send.hash)

        #Finalize the parent.
        for _ in range(6):
            mineBlock(rpc)

        #Spend it.
        spendingSend: Send = Send.fromJSON(vectors["spendingSend"])
        if rpc.meros.liveTransaction(spendingSend) != rpc.meros.live.recv():
            raise TestError("Meros didn't broadcast back a Send.")
        verify(rpc, spendingSend.hash)
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros didn't consider a verified Transaction's inputs as spent."
            )
        if rpc.call("transactions", "getUTXOs", {"address": otherAddress}) != [
            {
                "hash": spendingSend.hash.hex().upper(),
                "nonce": 0
            }
        ]:
            raise TestError(
                "Meros didn't consider a verified Transaction's outputs as UTXOs."
            )

        #Unverify the spending Send. This would also unverify the parent if it wasn't finalized.
        #This is done via causing a Merit Removal.
        #Uses two competing Datas to not change the Send's status to competing.
        datas: List[Data] = [Data(bytes(32), recipientPub)]
        for _ in range(2):
            datas.append(Data(datas[0].hash, datas[-1].hash))
        for data in datas:
            data.sign(recipient)
            data.beat(SpamFilter(5))
            if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
                raise TestError("Meros didn't broadcast back a Data.")
            verify(rpc, data.hash, mr=(datas[-1].hash == data.hash))
        #Verify the MeritRemoval happened and the spending Send is no longer verified.
        #These first two checks are more likely to symbolize a failure in testing methodology than Meros.
        if not rpc.call("merit", "getMerit", {"nick": 0})["malicious"]:
            raise TestError("Meros didn't create a Merit Removal.")
        if not rpc.call("consensus", "getStatus",
                        {"hash": send.hash.hex()})["verified"]:
            raise TestError("Finalized Transaction became unverified.")
        if rpc.call("consensus", "getStatus",
                    {"hash": spendingSend.hash.hex()})["verified"]:
            raise TestError(
                "Meros didn't unverify a Transaction which is currently below the required threshold."
            )
        #Even after unverification, since the Transaction still exists, the input shouldn't be considered a UTXO.
        if rpc.call("transactions", "getUTXOs", {"address": address}) != []:
            raise TestError(
                "Meros didn't consider a unverified yet existing Transaction's inputs as spent."
            )
        #That said, its outputs should no longer be considered a UTXO.
        if rpc.call("transactions", "getUTXOs",
                    {"address": otherAddress}) != []:
            raise TestError(
                "Meros considered a unverified Transaction's outputs as UTXOs."
            )

        raise SuccessError()
Beispiel #11
0
def GetBlockTest(rpc: RPC) -> None:
    blockchain: Blockchain
    claim: Claim
    send: Send
    datas: List[Data]

    txKey: Callable[[Dict[str, Any]], str] = lambda tx: tx["hash"]

    def verify() -> None:
        for b in range(len(blockchain.blocks)):
            block: Dict[str, Any] = rpc.call(
                "merit", "getBlock",
                {"block": blockchain.blocks[b].header.hash.hex().upper()},
                False)
            if rpc.call("merit", "getBlock", {"block": b}, False) != block:
                raise TestError(
                    "Meros reported different Blocks depending on if nonce/hash indexing."
                )

            #Python doesn't keep track of the removals.
            #That said, they should all be empty except for the last one.
            if b != (len(blockchain.blocks) - 1):
                if block["removals"] != []:
                    raise TestError("Meros reported the Block had removals.")
            del block["removals"]

            if blockchain.blocks[b].toJSON() != block:
                raise TestError(
                    "Meros's JSON serialization of Blocks differs from Python's."
                )

        #Test the key serialization of the first Block.
        #The final Block uses a nick, hence the value in this.
        if rpc.call("merit", "getBlock", {"block": 1},
                    False)["header"]["miner"] != PrivateKey(
                        0).toPublicKey().serialize().hex().upper():
            raise TestError("Meros didn't serialize a miner's key properly.")

        #Manually test the final, and most complex, block.
        final: Dict[str, Any] = rpc.call("merit", "getBlock",
                                         {"block": len(blockchain.blocks) - 1},
                                         False)
        final["transactions"].sort(key=txKey)
        final["removals"].sort()
        if final != {
                "hash":
                blockchain.blocks[-1].header.hash.hex().upper(),
                "header": {
                    "version":
                    blockchain.blocks[-1].header.version,
                    "last":
                    blockchain.blocks[-1].header.last.hex().upper(),
                    "contents":
                    blockchain.blocks[-1].header.contents.hex().upper(),
                    "packets":
                    blockchain.blocks[-1].header.packetsQuantity,
                    "sketchSalt":
                    blockchain.blocks[-1].header.sketchSalt.hex().upper(),
                    "sketchCheck":
                    blockchain.blocks[-1].header.sketchCheck.hex().upper(),
                    "miner":
                    blockchain.blocks[-1].header.minerKey.hex().upper()
                    if blockchain.blocks[-1].header.newMiner else
                    blockchain.blocks[-1].header.minerNick,
                    "time":
                    blockchain.blocks[-1].header.time,
                    "proof":
                    blockchain.blocks[-1].header.proof,
                    "signature":
                    blockchain.blocks[-1].header.signature.hex().upper()
                },
                "transactions":
                sorted([{
                    "hash": claim.hash.hex().upper(),
                    "holders": [0]
                }, {
                    "hash": send.hash.hex().upper(),
                    "holders": [0, 1, 2]
                }, {
                    "hash": datas[0].hash.hex().upper(),
                    "holders": [0, 2]
                }, {
                    "hash": datas[1].hash.hex().upper(),
                    "holders": [0, 1, 3]
                }, {
                    "hash": datas[2].hash.hex().upper(),
                    "holders": [0, 1, 2, 3, 4]
                }, {
                    "hash": datas[3].hash.hex().upper(),
                    "holders": [0, 1, 2, 3]
                }],
                       key=txKey),
                "elements": [
                    {
                        "descendant": "DataDifficulty",
                        "holder": 3,
                        "nonce": 0,
                        "difficulty": 8
                    },
                    {
                        "descendant": "SendDifficulty",
                        "holder": 0,
                        "nonce": 0,
                        "difficulty": 1
                    },
                    {
                        "descendant": "DataDifficulty",
                        "holder": 3,
                        "nonce": 0,
                        "difficulty": 4
                    },
                    {
                        "descendant": "DataDifficulty",
                        "holder": 4,
                        "nonce": 2,
                        "difficulty": 1
                    },
                    {
                        "descendant": "SendDifficulty",
                        "holder": 4,
                        "nonce": 1,
                        "difficulty": 3
                    },
                    {
                        "descendant": "SendDifficulty",
                        "holder": 2,
                        "nonce": 1,
                        "difficulty": 2
                    },
                    {
                        "descendant": "DataDifficulty",
                        "holder": 0,
                        "nonce": 0,
                        "difficulty": 7
                    },
                ],
                "removals": [0, 3],
                "aggregate":
                blockchain.blocks[-1].body.aggregate.serialize().hex().upper()
        }:
            raise TestError("Final Block wasn't correct.")

        #Test invalid calls.
        try:
            rpc.call("merit", "getBlock", {"block": 100}, False)
            raise Exception("")
        except Exception as e:
            if str(e) != "-2 Block not found.":
                raise TestError(
                    "getBlock didn't error when we used a non-existent nonce.")

        try:
            rpc.call("merit", "getBlock", {"block": -5}, False)
            raise Exception("")
        except Exception as e:
            if str(e) != "-32602 Invalid params.":
                raise TestError(
                    "getBlock didn't error when we used a negative (signed) integer for a nonce."
                )

        try:
            rpc.call(
                "merit", "getBlock", {
                    "block":
                    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                }, False)
            raise Exception("")
        except Exception as e:
            if str(e) != "-2 Block not found.":
                raise TestError(
                    "getBlock didn't error when we used a non-existent hash.")

        try:
            rpc.call("merit", "getBlock", {"block": ""}, False)
            raise Exception("")
        except Exception as e:
            if str(e) != "-32602 Invalid params.":
                raise TestError(
                    "getBlock didn't error when we used an invalid hash.")

    with open("e2e/Vectors/RPC/Merit/GetBlock.json", "r") as file:
        vectors: Dict[str, Any] = json.loads(file.read())
        blockchain = Blockchain.fromJSON(vectors["blockchain"])
        claim = Claim.fromJSON(vectors["claim"])
        send = Send.fromJSON(vectors["send"])
        datas = [Data.fromJSON(data) for data in vectors["datas"]]
        transactions: Transactions = Transactions.fromJSON(
            vectors["transactions"])
        Liver(rpc, vectors["blockchain"], transactions, {
            (len(blockchain.blocks) - 1): verify
        }).live()