Beispiel #1
0
    def fromSignedJSON(jsonArg: Dict[str, Any]) -> Any:
        json: Dict[str, Any] = dict(jsonArg)
        json["elements"] = list(json["elements"])
        json["elements"][0] = dict(json["elements"][0])
        json["elements"][1] = dict(json["elements"][1])
        json["elements"][0]["holder"] = json["holder"]
        json["elements"][1]["holder"] = json["holder"]

        e1: MeritRemovalElement = SignedVerification(bytes(32), 0)
        if json["elements"][0]["descendant"] == "Verification":
            e1 = SignedVerification.fromSignedJSON(json["elements"][0])
        elif json["elements"][0]["descendant"] == "VerificationPacket":
            e1 = SignedMeritRemovalVerificationPacket.fromSignedJSON(
                json["elements"][0])
        elif json["elements"][0]["descendant"] == "SendDifficulty":
            e1 = SignedSendDifficulty.fromSignedJSON(json["elements"][0])
        elif json["elements"][0]["descendant"] == "DataDifficulty":
            e1 = SignedDataDifficulty.fromSignedJSON(json["elements"][0])

        e2: MeritRemovalElement = SignedVerification(bytes(32), 0)
        if json["elements"][1]["descendant"] == "Verification":
            e2 = SignedVerification.fromSignedJSON(json["elements"][1])
        elif json["elements"][1]["descendant"] == "VerificationPacket":
            e2 = SignedMeritRemovalVerificationPacket.fromSignedJSON(
                json["elements"][1])
        elif json["elements"][1]["descendant"] == "SendDifficulty":
            e2 = SignedSendDifficulty.fromSignedJSON(json["elements"][1])
        elif json["elements"][1]["descendant"] == "DataDifficulty":
            e2 = SignedDataDifficulty.fromSignedJSON(json["elements"][1])

        return SignedMeritRemoval(e1, e2, json["holder"])
def HundredSeventyFiveTest(
  rpc: RPC
) -> None:
  file: IO[Any] = open("e2e/Vectors/Merit/HundredSeventyFive.json", "r")
  vectors: Dict[str, Any] = json.loads(file.read())
  file.close()

  transactions: Transactions = Transactions.fromJSON(vectors["transactions"])
  verif: SignedVerification = SignedVerification.fromSignedJSON(vectors["verification"])

  def sendDatasAndVerif() -> None:
    for tx in transactions.txs:
      if rpc.meros.liveTransaction(transactions.txs[tx]) != rpc.meros.live.recv():
        raise TestError("Meros didn't send us back the Data.")

    if rpc.meros.signedElement(verif) != rpc.meros.live.recv():
      raise TestError("Meros didn't send us back the Verification.")

  Liver(
    rpc,
    vectors["blockchain"],
    transactions,
    callbacks={
      1: sendDatasAndVerif
    }
  ).live([verif.hash])
Beispiel #3
0
def OneHundredPercentSketchTest(meros: Meros) -> None:
    vectors: Dict[str, Any]
    with open("e2e/Vectors/Merit/Sketches/OneHundredPercent.json",
              "r") as file:
        vectors = json.loads(file.read())

    blockchain: Blockchain = Blockchain.fromJSON(vectors["blockchain"])

    meros.liveConnect(blockchain.blocks[0].header.hash)
    meros.syncConnect(blockchain.blocks[0].header.hash)

    header: bytes = meros.liveBlockHeader(blockchain.blocks[1].header)
    meros.handleBlockBody(blockchain.blocks[1])
    if meros.live.recv() != header:
        raise TestError(
            "Meros didn't broadcast a BlockHeader for a Block it just added.")

    for data in vectors["datas"]:
        if meros.liveTransaction(Data.fromJSON(data)) != meros.live.recv():
            raise TestError("Meros didn't broadcast back a Data Transaction.")

    for verif in vectors["verifications"]:
        if meros.signedElement(
                SignedVerification.fromSignedJSON(verif)) != meros.live.recv():
            raise TestError("Meros didn't broadcast back a Verification.")

    header = meros.liveBlockHeader(blockchain.blocks[2].header)
    meros.handleBlockBody(blockchain.blocks[2])
    if meros.live.recv() != header:
        raise TestError(
            "Meros didn't broadcast a BlockHeader for a Block it just added.")
def UnmentionedBeatMentionedTest(
  rpc: RPC
) -> None:
  vectors: Dict[str, Any]
  with open("e2e/Vectors/Consensus/Families/UnmentionedBeatMentioned.json", "r") as file:
    vectors = json.loads(file.read())
  datas: List[Data] = [Data.fromJSON(data) for data in vectors["datas"]]
  verif: SignedVerification = SignedVerification.fromSignedJSON(vectors["verification"])

  def sendDatas() -> None:
    for d in range(len(datas)):
      if rpc.meros.liveTransaction(datas[d]) != rpc.meros.live.recv():
        raise TestError("Meros didn't broadcast a Data.")

    #Might as well send this now.
    if rpc.meros.signedElement(verif) != rpc.meros.live.recv():
      raise TestError("Meros didn't broadcast the Verification.")

  def verifyMentionedWon() -> None:
    if not rpc.call("consensus", "getStatus", [datas[2].hash.hex()])["verified"]:
      raise TestError("Meros didn't verify the only Transaction on chain which has finalized.")

  Liver(
    rpc,
    vectors["blockchain"],
    callbacks={
      41: sendDatas,
      47: verifyMentionedWon
    }
  ).live()
Beispiel #5
0
def MissingOneSketchTest(meros: Meros) -> None:
    vectors: Dict[str, Any]
    with open("e2e/Vectors/Merit/Sketches/MissingOne.json", "r") as file:
        vectors = json.loads(file.read())

    blockchain: Blockchain = Blockchain.fromJSON(vectors["blockchain"])

    meros.liveConnect(blockchain.blocks[0].header.hash)
    meros.syncConnect(blockchain.blocks[0].header.hash)

    header: bytes = meros.liveBlockHeader(blockchain.blocks[1].header)
    meros.handleBlockBody(blockchain.blocks[1])
    if meros.live.recv() != header:
        raise TestError(
            "Meros didn't broadcast a BlockHeader for a Block it just added.")

    for data in vectors["datas"]:
        if meros.liveTransaction(Data.fromJSON(data)) != meros.live.recv():
            raise TestError("Meros didn't broadcast back a Data Transaction.")

    for verif in vectors["verifications"]:
        if meros.signedElement(
                SignedVerification.fromSignedJSON(verif)) != meros.live.recv():
            raise TestError("Meros didn't broadcast back a Verification.")

    header = meros.liveBlockHeader(blockchain.blocks[2].header)
    meros.handleBlockBody(blockchain.blocks[2], 1)

    if MessageType(meros.sync.recv()[0]) != MessageType.SketchHashRequests:
        raise TestError("Meros didn't request the packet it's missing.")
    meros.packet(VerificationPacket.fromJSON(vectors["packet"]))

    if meros.live.recv() != header:
        raise TestError(
            "Meros didn't broadcast a BlockHeader for a Block it just added.")
Beispiel #6
0
def TwoHundredThirtyEightTest(
  rpc: RPC
) -> None:
  vectors: Dict[str, Any]
  with open("e2e/Vectors/Transactions/Prune/TwoHundredThirtyEight.json", "r") as file:
    vectors = json.loads(file.read())

  datas: List[Data] = [Data.fromJSON(data) for data in vectors["datas"]]
  verif: SignedVerification = SignedVerification.fromSignedJSON(vectors["verification"])

  def sendDatas() -> None:
    for d in range(len(datas)):
      if rpc.meros.liveTransaction(datas[d]) != rpc.meros.live.recv():
        raise TestError("Meros didn't broadcast a Data.")

    if rpc.meros.signedElement(verif) != rpc.meros.live.recv():
      raise TestError("Meros didn't broadcast the Verification.")

  Liver(
    rpc,
    vectors["blockchain"],
    callbacks={
      42: sendDatas
    }
  ).live()
  def sendDatas() -> None:
    for data in datas:
      if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
        raise TestError("Meros didn't send back the Data.")

    #Send the beaten Data's descendant's verification.
    if rpc.meros.signedElement(SignedVerification.fromSignedJSON(vectors["verification"])) != rpc.meros.live.recv():
      raise TestError("Meros didn't send back the SignedVerification.")
    def sendDatas() -> None:
        for data in datas:
            if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
                raise TestError("Meros didn't send back the Data.")

        #Send the winning descendant Data's verification.
        verif: SignedVerification = SignedVerification.fromSignedJSON(
            vectors["verification"])
        if rpc.meros.signedElement(verif) != rpc.meros.live.recv():
            raise TestError("Meros didn't send back the SignedVerification.")

        #The Liver thinks we sent this packet, so it shouldn't have to.
        #That said, that'd only be true if this was included in the Sketcher.
        #As its parent is unmentioned, it won't be.
        del rpc.meros.sentVerifs[verif.hash]
Beispiel #9
0
    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",
                                          {"hash": 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.")
def PartialArchiveTest(rpc: RPC) -> None:
    vectors: Dict[str, Any]
    with open("e2e/Vectors/Consensus/Verification/PartialArchive.json",
              "r") as file:
        vectors = json.loads(file.read())

    data: Data = Data.fromJSON(vectors["data"])
    svs: List[SignedVerification] = [
        SignedVerification.fromSignedJSON(vectors["verifs"][0]),
        SignedVerification.fromSignedJSON(vectors["verifs"][1])
    ]

    key: PrivateKey = PrivateKey(
        bytes.fromhex(rpc.call("personal", "getMiner")))

    def sendDataAndVerifications() -> None:
        if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
            raise TestError(
                "Meros didn't rebroadcast a Transaction we sent it.")
        for sv in svs:
            if rpc.meros.signedElement(sv) != rpc.meros.live.recv():
                raise TestError(
                    "Meros didn't rebroadcast a SignedVerification we sent it."
                )

        #As we don't have a quality RPC route for this, we need to use getTemplate.
        if bytes.fromhex(
                rpc.call("merit", "getBlockTemplate",
                         [key.toPublicKey().serialize().hex()
                          ])["header"])[36:68] != BlockHeader.createContents(
                              [VerificationPacket(data.hash, [0, 1])]):
            raise TestError(
                "New Block template doesn't have a properly created packet.")

    def verifyRecreation() -> None:
        template: Dict[str,
                       Any] = rpc.call("merit", "getBlockTemplate",
                                       [key.toPublicKey().serialize().hex()])
        if bytes.fromhex(
                template["header"])[36:68] != BlockHeader.createContents(
                    [VerificationPacket(data.hash, [1])]):
            raise TestError(
                "New Block template doesn't have a properly recreated packet.")

        #Mining it further verifies the internal state.
        header: bytes = bytes.fromhex(template["header"])
        proof: int = 0
        sig: bytes
        while True:
            initial: bytes = RandomX(header +
                                     proof.to_bytes(4, byteorder="little"))
            sig = key.sign(initial).serialize()
            final: bytes = RandomX(initial + sig)
            if (int.from_bytes(final, "little") *
                    template["difficulty"]) < int.from_bytes(
                        bytes.fromhex("FF" * 32), "little"):
                break
            proof += 1

        rpc.call("merit", "publishBlock", [
            template["id"],
            (header + proof.to_bytes(4, byteorder="little") + sig).hex()
        ])

        raise SuccessError(
            "Stop Liver from trying to verify the vector chain which doesn't have this Block."
        )

    #We may not want to use Liver here.
    #There's a very small Block count and we can't let it terminate (hence the SE).
    with raises(SuccessError):
        Liver(rpc,
              vectors["blockchain"],
              callbacks={
                  2: sendDataAndVerifications,
                  3: verifyRecreation
              }).live()
Beispiel #11
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 #12
0
def VerifyCompetingTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "e2e/Vectors/Consensus/MeritRemoval/VerifyCompeting.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Datas.
    datas: List[Data] = [
        Data.fromJSON(vectors["datas"][0]),
        Data.fromJSON(vectors["datas"][1]),
        Data.fromJSON(vectors["datas"][2])
    ]

    #Transactions.
    transactions: Transactions = Transactions()
    for data in datas:
        transactions.add(data)

    #Initial Data's Verification.
    verif: SignedVerification = SignedVerification.fromSignedJSON(
        vectors["verification"])

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

    #Create and execute a Liver to cause a Signed MeritRemoval.
    def sendElements() -> None:
        #Send the Datas.
        for data in datas:
            if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
                raise TestError("Meros didn't send us the Data.")

        #Send the initial Data's verification.
        if rpc.meros.signedElement(verif) != rpc.meros.live.recv():
            raise TestError("Meros didn't us the initial Data's Verification.")

        #Send the first Element.
        if rpc.meros.signedElement(removal.se1) != rpc.meros.live.recv():
            raise TestError("Meros didn't send us the Verification.")

        #Trigger the MeritRemoval.
        rpc.meros.signedElement(removal.se2)
        if rpc.meros.live.recv() != (MessageType.SignedMeritRemoval.toByte() +
                                     removal.signedSerialize()):
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 1, 1, removal.holder, True)

    Liver(rpc,
          vectors["blockchain"],
          transactions,
          callbacks={
              1: sendElements,
              2: lambda: verifyMeritRemoval(rpc, 1, 1, removal.holder, False)
          }).live()

    #Create and execute a Liver to handle a Signed MeritRemoval.
    def sendMeritRemoval() -> None:
        #Send the Datas.
        for data in datas:
            if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
                raise TestError("Meros didn't send us the Data.")

        #Send the initial Data's verification.
        if rpc.meros.signedElement(verif) != rpc.meros.live.recv():
            raise TestError("Meros didn't us the initial Data's Verification.")

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

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

    #Create and execute a Syncer to handle a Signed MeritRemoval.
    Syncer(rpc, vectors["blockchain"], transactions).sync()
    verifyMeritRemoval(rpc, 1, 1, removal.holder, False)
Beispiel #13
0
def MatchesHeaderQuantityTest(meros: Meros) -> None:
    #Create an instance of Merit to make sure the RandomX VM key was set.
    Merit()

    blocks: List[Block]
    txs: List[Data] = []
    verifs: List[SignedVerification] = []
    with open(
            "e2e/Vectors/Merit/TwoHundredSeventyFour/MatchesHeaderQuantity.json",
            "r") as file:
        vectors: Dict[str, Any] = json.loads(file.read())
        blocks = [Block.fromJSON(block) for block in vectors["blocks"]]
        txs = [Data.fromJSON(tx) for tx in vectors["transactions"]]
        verifs = [
            SignedVerification.fromSignedJSON(verif)
            for verif in vectors["verifications"]
        ]

    #Connect.
    meros.liveConnect(blocks[0].header.last)
    meros.syncConnect(blocks[0].header.last)

    #Send a single Block to earn Merit.
    meros.liveBlockHeader(blocks[0].header)
    meros.handleBlockBody(blocks[0])

    #Send the header.
    meros.liveBlockHeader(blocks[1].header)

    #Fail Sketch Resolution, and send a different amount of sketch hashes.
    meros.handleBlockBody(blocks[1], 0)
    if MessageType(meros.sync.recv()[0]) != MessageType.SketchHashesRequest:
        raise TestError(
            "Meros didn't request the hashes after failing sketch resolution.")

    #Send a quantity of sketch hashes that doesn't match the header.
    meros.sketchHashes([
        Sketch.hash(blocks[1].header.sketchSalt,
                    VerificationPacket(tx.hash, [0])) for tx in txs
    ])
    try:
        if len(meros.sync.recv()) == 0:
            raise TestError()
        raise Exception()
    except TestError:
        pass
    except Exception:
        raise TestError("Meros tried to further sync an invalid Block Body.")

    #Sleep so we can reconnect.
    sleep(65)

    #Repeat setup.
    meros.liveConnect(blocks[0].header.last)
    meros.syncConnect(blocks[0].header.last)

    #Send two Transactions.
    for i in range(2):
        meros.liveTransaction(txs[i])
        meros.signedElement(verifs[i])

    #Send the header and a large enough sketch to cause resolution.
    meros.liveBlockHeader(blocks[1].header)
    meros.handleBlockBody(blocks[1], 3)

    #Should now have been disconnected thanks to having 5 hashes.
    try:
        if len(meros.sync.recv()) == 0:
            raise TestError()
        raise Exception()
    except TestError:
        pass
    except Exception:
        raise TestError("Meros tried to further sync an invalid Block Body.")