Пример #1
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 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()
Пример #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.")
Пример #4
0
  def testBlockchain(
    b: int
  ) -> None:
    #Data.
    data: Data = Data.fromJSON(vectors["data"])

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

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

      rpc.meros.signedElement(removal)
      try:
        if len(rpc.meros.live.recv()) != 0:
          raise Exception()
      except TestError:
        raise SuccessError("Meros rejected our MeritRemoval created from the same Element.")
      except Exception:
        raise TestError("Meros accepted our MeritRemoval created from the same Element.")

    Liver(
      rpc,
      vectors["blockchain"],
      callbacks={
        1: sendMeritRemoval
      }
    ).live()
Пример #5
0
def LowerHashTieBreakTest(rpc: RPC) -> None:
    vectors: Dict[str, Any]
    with open("e2e/Vectors/Consensus/Families/LowerHashTieBreak.json",
              "r") as file:
        vectors = json.loads(file.read())
    datas: List[Data] = [Data.fromJSON(data) for data in vectors["datas"]]

    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.")

    def verifyLowerHashWon() -> None:
        data: Data = datas[1]
        if int.from_bytes(data.hash, "little") > int.from_bytes(
                datas[2].hash, "little"):
            data = datas[2]
        if not rpc.call("consensus", "getStatus",
                        {"hash": data.hash.hex()})["verified"]:
            raise TestError(
                "Meros didn't verify the tied Transaction with a lower hash.")

    Liver(rpc,
          vectors["blockchain"],
          callbacks={
              40: sendDatas,
              46: verifyLowerHashWon
          }).live()
Пример #6
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.")
Пример #7
0
def NodeThresholdTest(rpc: RPC) -> None:
    edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)

    dataFilter: SpamFilter = SpamFilter(5)

    datas: List[Data] = [Data(bytes(32), edPrivKey.get_verifying_key())]
    datas[-1].sign(edPrivKey)
    datas[-1].beat(dataFilter)

    def verifyThreshold(b: int) -> None:
        rpc.meros.liveTransaction(datas[-1])
        datas.append(Data(datas[-1].hash, b"a"))
        datas[-1].sign(edPrivKey)
        datas[-1].beat(dataFilter)

        #Swallow the new Data(s).
        if b == 1:
            rpc.meros.live.recv()
        rpc.meros.live.recv()

        #Check the threshold.
        threshold: int = rpc.call("consensus", "getStatus",
                                  {"hash": datas[-2].hash.hex()})["threshold"]
        if b < 9:
            if threshold != ((max(b + 6, 5) // 5 * 4) + 1):
                raise TestError(
                    "Meros didn't calculate the right node threshold. That said, this isn't defined by the protocol."
                )
        elif threshold != 5:
            raise TestError("Meros didn't lower the node threshold.")

    with open("e2e/Vectors/Merit/BlankBlocks.json", "r") as file:
        Liver(rpc, json.loads(file.read())[:9],
              everyBlock=verifyThreshold).live()
Пример #8
0
def VUnknownSignedTest(rpc: RPC) -> None:
    file: IO[Any] = open("e2e/Vectors/Merit/BlankBlocks.json", "r")
    chain: Blockchain = Blockchain.fromJSON(json.loads(file.read()))
    file.close()

    #Send a single block so we have a miner.
    rpc.meros.liveConnect(chain.blocks[0].header.hash)
    rpc.meros.syncConnect(chain.blocks[0].header.hash)
    header: bytes = rpc.meros.liveBlockHeader(chain.blocks[1].header)
    if MessageType(rpc.meros.sync.recv()[0]) != MessageType.BlockBodyRequest:
        raise TestError("Meros didn't ask for the body.")
    rpc.meros.blockBody(chain.blocks[1])
    if rpc.meros.live.recv() != header:
        raise TestError("Meros didn't broadcast the header.")

    #Create a valid Data.
    #Uneccessary at this time, but good preparation for the future.
    privKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
    data: Data = Data(bytes(32), privKey.get_verifying_key().to_bytes())
    data.sign(privKey)
    data.beat(SpamFilter(5))

    #Sign the Data.
    verif: SignedVerification = SignedVerification(data.hash)
    verif.sign(0, PrivateKey(0))

    #Run twice. The first shouldn't send the Transaction. The second should.
    for i in range(2):
        rpc.meros.signedElement(verif)
        if MessageType(
                rpc.meros.sync.recv()[0]) != MessageType.TransactionRequest:
            raise TestError("Meros didn't request the transaction.")

        if i == 0:
            #When we send DataMissing, we should be disconnected within a few seconds.
            rpc.meros.dataMissing()
            start: int = int(time())
            try:
                rpc.meros.sync.recv()
            except Exception:
                #More than a few seconds is allowed as Meros's own SyncRequest must timeout.
                if int(time()) - start > 10:
                    raise TestError(
                        "Meros didn't disconnect us for sending a Verification of a non-existent Transaction."
                    )
            #Clear our invalid connections.
            rpc.meros.live.connection.close()
            rpc.meros.sync.connection.close()
            sleep(65)
            #Init new ones.
            rpc.meros.liveConnect(chain.blocks[0].header.hash)
            rpc.meros.syncConnect(chain.blocks[0].header.hash)

        else:
            rpc.meros.syncTransaction(data)
            sleep(2)
            if not rpc.call("consensus", "getStatus",
                            [data.hash.hex()])["verifiers"]:
                raise TestError("Meros didn't add the Verification.")
Пример #9
0
def PruneUnaddableTest(rpc: RPC) -> None:
    file: IO[Any] = open("e2e/Vectors/Transactions/PruneUnaddable.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    pruned: bytes = Data.fromJSON(vectors["datas"][2]).hash
    prunedDescendant: bytes = Data.fromJSON(vectors["datas"][3]).hash

    def sendDatas() -> None:
        for data in vectors["datas"]:
            if rpc.meros.liveTransaction(
                    Data.fromJSON(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 verifyAdded() -> None:
        rpc.call("transactions", "getTransaction", [pruned.hex()])
        rpc.call("consensus", "getStatus", [pruned.hex()])

    def verifyPruned() -> None:
        try:
            rpc.call("transactions", "getTransaction", [pruned.hex()])
            rpc.call("transactions", "getTransaction",
                     [prunedDescendant.hex()])
            rpc.call("consensus", "getStatus", [pruned.hex()])
            rpc.call("consensus", "getStatus", [prunedDescendant.hex()])
            raise Exception()
        except TestError:
            pass
        except Exception:
            raise TestError("Meros didn't prune the Transaction.")

    #Create and execute a Liver.
    Liver(rpc,
          vectors["blockchain"],
          callbacks={
              1: sendDatas,
              2: verifyAdded,
              8: verifyPruned
          }).live()
Пример #10
0
    def sendDatas() -> None:
        for data in vectors["datas"]:
            if rpc.meros.liveTransaction(
                    Data.fromJSON(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.")
Пример #11
0
def HundredThirtyFiveTest(
  rpc: RPC
) -> None:
  file: IO[Any] = open("e2e/Vectors/Consensus/MeritRemoval/HundredThirtyFive.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)

  #First MeritRemoval.
  mr: SignedMeritRemoval = SignedMeritRemoval.fromSignedJSON(vectors["removal"])

  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 and verify the original MeritRemoval.
    if rpc.meros.signedElement(mr) != rpc.meros.live.recv():
      raise TestError("Meros didn't send us the Merit Removal.")
    verifyMeritRemoval(rpc, 1, 1, mr.holder, True)

  Liver(
    rpc,
    vectors["blockchain"],
    transactions,
    callbacks={
      1: sendMeritRemoval
    }
  ).live()
Пример #12
0
 def fromJSON(json: Dict[str, Dict[str, Any]]) -> Any:
     result = Transactions()
     for tx in json:
         if json[tx]["descendant"] == "Claim":
             result.add(Claim.fromJSON(json[tx]))
         elif json[tx]["descendant"] == "Send":
             result.add(Send.fromJSON(json[tx]))
         elif json[tx]["descendant"] == "Data":
             result.add(Data.fromJSON(json[tx]))
         else:
             raise Exception("JSON has an unsupported Transaction type: " +
                             json[tx]["descendant"])
     return result
Пример #13
0
def DataTest(rpc: RPC) -> None:
    privKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
    pubKey: bytes = privKey.get_verifying_key()

    genesis: bytes = Blockchain().blocks[0].header.hash
    spamFilter: SpamFilter = SpamFilter(5)

    data: Data = Data(bytes(32), pubKey)
    data.sign(privKey)
    data.beat(spamFilter)

    rpc.meros.liveConnect(genesis)
    rpc.meros.liveTransaction(data)
    verifyTransaction(rpc, data)
Пример #14
0
def MultiplePacketsTest(rpc: RPC) -> None:
    #Spawn a Blockchain just to set the RandomX key.
    _: Blockchain = Blockchain()

    vectors: Dict[str, Any]
    with open("e2e/Vectors/Merit/MultiplePackets.json", "r") as file:
        vectors = json.loads(file.read())

    data: Data = Data.fromJSON(vectors["data"])
    block: Block = Block.fromJSON(vectors["blockchain"][-1])

    def sendDataAndBlock() -> None:
        #Send the Data.
        if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
            raise TestError("Meros didn't send back the Data.")

        rpc.meros.liveBlockHeader(block.header)
        rpc.meros.handleBlockBody(block)
        msg: bytes = rpc.meros.sync.recv()
        if MessageType(msg[0]) != MessageType.SketchHashRequests:
            raise TestError("Meros didn't request the packets for this Block.")

        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="little")):
            sketchHash: int = int.from_bytes(msg[37 + (h * 8):45 + (h * 8)],
                                             byteorder="little")
            if sketchHash not in packets:
                raise TestError("Meros asked for a non-existent Sketch Hash.")
            rpc.meros.packet(packets[sketchHash])

        try:
            if MessageType(
                    rpc.meros.live.recv()[0]) == MessageType.BlockHeader:
                raise TestError("Meros added the Block.")
        except Exception as e:
            if str(e) != "Meros added the Block.":
                raise SuccessError()

    with raises(SuccessError):
        Liver(rpc, vectors["blockchain"], callbacks={
            2: sendDataAndBlock
        }).live()
Пример #15
0
def HundredSixSignedElementsTest(
  rpc: RPC
) -> None:
  #Solely used to get the genesis Block hash.
  blockchain: Blockchain = Blockchain()

  edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
  blsPrivKey: PrivateKey = PrivateKey(0)
  sig: Signature = blsPrivKey.sign(bytes())

  #Create a Data for the Verification.
  data: Data = Data(bytes(32), edPrivKey.get_verifying_key())
  data.sign(edPrivKey)
  data.beat(SpamFilter(5))

  #Create a signed Verification, SendDifficulty, and DataDifficulty.
  elements: List[SignedElement] = [
    SignedVerification(data.hash, 1, sig),
    SignedSendDifficulty(0, 0, 1, sig),
    SignedDataDifficulty(0, 0, 1, sig)
  ]

  dataSent: bool = False
  for elem in elements:
    #Handshake with the node.
    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)

    #Send the Data if we have yet to.
    if not dataSent:
      if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
        raise TestError("Data wasn't rebroadcasted.")
      dataSent = True

    #Send the Element.
    rpc.meros.signedElement(elem)

    #Sleep for thirty seconds to make sure Meros realizes our connection is dead.
    sleep(30)

    #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.")
Пример #16
0
def PruneUnaddableTest(rpc: RPC) -> None:
    vectors: Dict[str, Any]
    with open("e2e/Vectors/Transactions/Prune/PruneUnaddable.json",
              "r") as file:
        vectors = json.loads(file.read())

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

    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]

    def verifyAdded() -> None:
        for data in datas:
            rpc.call("transactions", "getTransaction",
                     {"hash": data.hash.hex()})
            rpc.call("consensus", "getStatus", {"hash": data.hash.hex()})

    def verifyPruned() -> None:
        for data in datas[2:]:
            with raises(TestError):
                rpc.call("transactions", "getTransaction",
                         {"hash": data.hash.hex()})
            with raises(TestError):
                rpc.call("consensus", "getStatus", {"hash": data.hash.hex()})

    Liver(rpc,
          vectors["blockchain"],
          callbacks={
              1: sendDatas,
              2: verifyAdded,
              7: verifyPruned
          }).live()
Пример #17
0
    def verifyThreshold(b: int) -> None:
        rpc.meros.liveTransaction(datas[-1])
        datas.append(Data(datas[-1].hash, b"a"))
        datas[-1].sign(edPrivKey)
        datas[-1].beat(dataFilter)

        #Swallow the new Data(s).
        if b == 1:
            rpc.meros.live.recv()
        rpc.meros.live.recv()

        #Check the threshold.
        threshold: int = rpc.call("consensus", "getStatus",
                                  {"hash": datas[-2].hash.hex()})["threshold"]
        if b < 9:
            if threshold != ((max(b + 6, 5) // 5 * 4) + 1):
                raise TestError(
                    "Meros didn't calculate the right node threshold. That said, this isn't defined by the protocol."
                )
        elif threshold != 5:
            raise TestError("Meros didn't lower the node threshold.")
Пример #18
0
def PruneUnaddableTest(
  rpc: RPC
) -> None:
  file: IO[Any] = open("e2e/Vectors/Transactions/PruneUnaddable.json", "r")
  vectors: Dict[str, Any] = json.loads(file.read())
  file.close()

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

  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 verifyAdded() -> None:
    for data in datas:
      rpc.call("transactions", "getTransaction", [data.hash.hex()])
      rpc.call("consensus", "getStatus", [data.hash.hex()])

  #def verifyPruned() -> None:
  #  for data in datas[2:]:
  #    with raises(TestError):
  #      rpc.call("transactions", "getTransaction", [data.hash.hex()])
  #    with raises(TestError):
  #      rpc.call("consensus", "getStatus", [data.hash.hex()])

  Liver(
    rpc,
    vectors["blockchain"],
    callbacks={
      1: sendDatas,
      2: verifyAdded
    }
  ).live()
Пример #19
0
def DataTest(rpc: RPC) -> None:
    #Get the genesis hash.
    genesis: bytes = Blockchain().blocks[0].header.hash

    #Create the Spam Filter.
    spamFilter: SpamFilter = SpamFilter(5)

    #Create the Data.
    data: Data = Data(bytes(32), pubKey.to_bytes())
    data.sign(privKey)
    data.beat(spamFilter)

    #Handshake with the node.
    rpc.meros.liveConnect(genesis)

    #Send the Data.
    rpc.meros.liveTransaction(data)

    #Sleep for 100 milliseconds.
    sleep(0.1)

    #Verify the Data.
    verifyTransaction(rpc, data)
Пример #20
0
dataFilter: SpamFilter = SpamFilter(5)

#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()

#Add 1 Blank Block.
for i in range(1):
  merit.add(Block.fromJSON(blankBlocks[i]))

#Create the Data and a successor.
first: Data = Data(bytes(32), edPubKey.to_bytes())
first.sign(edPrivKey)
first.beat(dataFilter)
transactions.add(first)

second: Data = Data(first.hash, bytes(1))
second.sign(edPrivKey)
second.beat(dataFilter)
transactions.add(second)

#Verify them.
firstVerif: SignedVerification = SignedVerification(first.hash)
firstVerif.sign(0, blsPrivKey)

secondVerif: SignedVerification = SignedVerification(second.hash)
secondVerif.sign(0, blsPrivKey)
Пример #21
0
    def live(self, ignorePackets: List[bytes] = []) -> None:
        #Handshake with the node.
        self.rpc.meros.liveConnect(self.merit.blockchain.blocks[0].header.hash)
        self.rpc.meros.syncConnect(self.merit.blockchain.blocks[0].header.hash)

        #Send each Block.
        for b in range(1, len(self.merit.blockchain.blocks)):
            block: Block = self.merit.blockchain.blocks[b]

            #Set loop variables with pending data.
            pendingBody: bool = True
            pendingPackets: List[bytes] = []
            pendingTXs: List[bytes] = []
            for packet in block.body.packets:
                if packet.hash in ignorePackets:
                    continue
                pendingPackets.append(packet.hash)

                #Don't include sent Transactions or independently created Block Data.
                if not ((packet.hash in self.rpc.meros.sentTXs) or
                        (packet.hash == (Data(self.merit.blockchain.genesis,
                                              block.header.last).hash))):
                    pendingTXs.append(packet.hash)

            for elem in block.body.elements:
                if isinstance(elem, MeritRemoval):
                    if (isinstance(elem.e1, (Verification, VerificationPacket))
                            and (elem.e1.hash not in self.rpc.meros.sentTXs)
                            and (elem.e1.hash not in pendingTXs)):
                        pendingTXs.append(elem.e1.hash)

                    if (isinstance(elem.e2, (Verification, VerificationPacket))
                            and (elem.e2.hash not in self.rpc.meros.sentTXs)
                            and (elem.e2.hash not in pendingTXs)):
                        pendingTXs.append(elem.e2.hash)

            self.rpc.meros.liveBlockHeader(block.header)

            reqHash: bytes = bytes()
            while True:
                #If we sent every bit of data, break.
                if ((not pendingBody) and (not pendingPackets)
                        and (not pendingTXs)):
                    break

                #Receive the next message.
                msg: bytes = self.rpc.meros.sync.recv()

                if MessageType(msg[0]) == MessageType.BlockBodyRequest:
                    reqHash = msg[1:33]

                    if not pendingBody:
                        raise TestError(
                            "Meros asked for the same Block Body multiple times."
                        )
                    if reqHash != block.header.hash:
                        raise TestError(
                            "Meros asked for a Block Body that didn't belong to the Block we just sent it."
                        )

                    self.rpc.meros.blockBody(block)
                    pendingBody = False

                elif MessageType(msg[0]) == MessageType.SketchHashesRequest:
                    reqHash = msg[1:33]
                    if not block.body.packets:
                        raise TestError(
                            "Meros asked for Sketch Hashes from a Block without any."
                        )
                    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))

                    self.rpc.meros.sketchHashes(hashes)

                elif MessageType(msg[0]) == MessageType.SketchHashRequests:
                    reqHash = msg[1:33]
                    if not block.body.packets:
                        raise TestError(
                            "Meros asked for Verification Packets from a Block without any."
                        )
                    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="little")):
                        sketchHash: int = int.from_bytes(msg[37 + (h * 8):45 +
                                                             (h * 8)],
                                                         byteorder="little")
                        if sketchHash not in packets:
                            raise TestError(
                                "Meros asked for a non-existent Sketch Hash.")
                        self.rpc.meros.packet(packets[sketchHash])

                        #Delete the VerificationPacket from pending.
                        del pendingPackets[pendingPackets.index(
                            packets[sketchHash].hash)]

                    #Make sure Meros asked for every packet.
                    if pendingPackets:
                        raise TestError(
                            "Meros didn't ask for every Verification Packet.")

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

                    if self.transactions is None:
                        raise TestError(
                            "Meros asked for a Transaction when we have none.")
                    if reqHash not in pendingTXs:
                        raise TestError(
                            "Meros asked for a non-existent Transaction, a Transaction part of a different Block, or an already sent Transaction."
                        )

                    self.rpc.meros.syncTransaction(
                        self.transactions.txs[reqHash])

                    #Delete the Transaction from pending.
                    del pendingTXs[pendingTXs.index(reqHash)]

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

            #Receive the BlockHeader from Meros.
            if MessageType(
                    self.rpc.meros.live.recv()[0]) != MessageType.BlockHeader:
                raise TestError("Meros didn't broadcast the new BlockHeader.")

            #Add any new nicks to the lookup table.
            if self.merit.blockchain.blocks[b].header.newMiner:
                self.merit.state.nicks.append(
                    self.merit.blockchain.blocks[b].header.minerKey)

            #If there's a callback at this height, call it.
            if b in self.callbacks:
                self.callbacks[b]()

            #Execute the every-Block callback, if it exists.
            if self.everyBlock is not None:
                self.everyBlock(b)

        #Verify the Blockchain.
        verifyBlockchain(self.rpc, self.merit.blockchain)

        #Verify the Transactions.
        if self.transactions is not None:
            verifyTransactions(self.rpc, self.transactions)

        #Reset the node.
        self.rpc.reset()
Пример #22
0
def TwoHundredThirtyFiveTest(rpc: RPC) -> None:
    blockchain: Blockchain = Blockchain()
    dataFilter: SpamFilter = SpamFilter(5)

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

    #Mine one Block to the node.
    blsPrivKey: PrivateKey = PrivateKey(
        bytes.fromhex(rpc.call("personal", "getMiner")))
    blsPubKey: bytes = blsPrivKey.toPublicKey().serialize()

    #Call getBlockTemplate just to get an ID.
    #Skips the need to write a sync loop for the BlockBody.
    template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate",
                                        [blsPubKey.hex()])

    #Mine a Block.
    block = Block(
        BlockHeader(0, blockchain.blocks[0].header.hash, bytes(32), 1,
                    bytes(4), bytes(32), blsPubKey,
                    blockchain.blocks[0].header.time + 1200, 0), BlockBody())
    block.mine(blsPrivKey, blockchain.difficulty())
    blockchain.add(block)

    rpc.call("merit", "publishBlock",
             [template["id"], block.serialize().hex()])

    #Send Meros a Data and receive its Verification to make sure it's verifying Transactions in the first place.
    data: Data = Data(bytes(32), edPubKey.to_bytes())
    data.sign(edPrivKey)
    data.beat(dataFilter)

    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)
    if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
        raise TestError("Meros didn't send back the Data.")
    if MessageType(rpc.meros.live.recv()[0]) != MessageType.SignedVerification:
        raise TestError("Meros didn't send us its SignedVerification.")

    #Close our connection and mine 8 Blocks so its Merit is locked.
    rpc.meros.live.connection.close()
    for _ in range(8):
        block = Block(
            BlockHeader(0, blockchain.blocks[-1].header.hash, bytes(32), 1,
                        bytes(4), bytes(32), 0,
                        blockchain.blocks[-1].header.time + 1200, 0),
            BlockBody())
        #Reusing its key is fine as mining doesn't count as participation.
        block.mine(blsPrivKey, blockchain.difficulty())
        blockchain.add(block)

    #Sleep 30 seconds to make sure Meros noted we disconnected, and then reconnect.
    sleep(30)
    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)
    rpc.meros.syncConnect(blockchain.blocks[0].header.hash)

    #Sync the Blocks.
    for b in range(8):
        header: bytes = rpc.meros.liveBlockHeader(blockchain.blocks[b +
                                                                    2].header)
        if rpc.meros.sync.recv() != (MessageType.BlockBodyRequest.toByte() +
                                     blockchain.blocks[b + 2].header.hash):
            raise TestError("Meros didn't request the BlockBody.")
        rpc.meros.blockBody(blockchain.blocks[b + 2])
        if rpc.meros.live.recv() != header:
            raise TestError("Meros didn't send back the header.")
        if MessageType(
                rpc.meros.live.recv()[0]) != MessageType.SignedVerification:
            raise TestError("Meros didn't verify this Block's data.")

    #Verify its Merit is locked.
    #Theoretically, all code after this check is unecessary.
    #Meros verifies a Block's Data after updating its State.
    #Therefore, if the above last Block had its Data verified, this issue should be closed.
    #That said, the timing is a bit too tight for comfort.
    #Better safe than sorry. Hence why the code after this check exists.
    if rpc.call("merit", "getMerit", [0])["status"] != "Locked":
        raise TestError("Merit wasn't locked when it was supposed to be.")

    #Send it a Transaction and make sure Meros verifies it, despite having its Merit locked.
    data = Data(data.hash, edPubKey.to_bytes())
    data.sign(edPrivKey)
    data.beat(dataFilter)

    if rpc.meros.liveTransaction(data) != rpc.meros.live.recv():
        raise TestError("Meros didn't send back the Data.")
    if MessageType(rpc.meros.live.recv()[0]) != MessageType.SignedVerification:
        raise TestError("Meros didn't send us its SignedVerification.")
Пример #23
0
dataFilter: SpamFilter = SpamFilter(5)

#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()

#Add 5 Blank Blocks.
for i in range(5):
    merit.add(Block.fromJSON(blankBlocks[i]))

#Create the Data.
data: Data = Data(bytes(32), edPubKey.to_bytes())
data.sign(edPrivKey)
data.beat(dataFilter)
transactions.add(data)

#Verify it.
verif: SignedVerification = SignedVerification(data.hash)
verif.sign(0, blsPrivKey)

#Generate another 6 Blocks.
#Next block should have a packet.
block: Block = Block(
    BlockHeader(
        0, merit.blockchain.last(),
        BlockHeader.createContents([VerificationPacket(verif.hash, [0])]), 1,
        bytes(4),
Пример #24
0
def HundredThirtyThreeTest(
  rpc: RPC
) -> None:
  file: IO[Any] = open("e2e/Vectors/Consensus/MeritRemoval/HundredThirtyThree.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)

  def testBlockchain(
    i: int
  ) -> None:
    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 Block containing the modified Merit Removal.
      block: Block = Block.fromJSON(vectors["blockchains"][i][-1])
      rpc.meros.liveBlockHeader(block.header)

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

      #Handle sync requests.
      reqHash: bytes = bytes()
      while True:
        if blockBodySynced:
          #Sleep for a second so Meros handles the Block.
          sleep(1)

          #Try receiving from the Live socket, where Meros sends keep-alives.
          try:
            if len(rpc.meros.live.recv()) != 0:
              raise Exception()
          except TestError:
            #Verify the height is 2.
            #The genesis Block and the Block granting Merit.
            try:
              if rpc.call("merit", "getHeight") != 2:
                raise Exception()
            except Exception:
              raise TestError("Node added a Block containg a repeat MeritRemoval.")

            #Since the node didn't add the Block, raise SuccessError.
            raise SuccessError("Node didn't add a Block containing a repeat MeritRemoval.")
          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.
          blockBodySynced = True
          rpc.meros.blockBody(block)

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

    Liver(
      rpc,
      vectors["blockchains"][i],
      transactions,
      callbacks={
        1: sendMeritRemoval
      }
    ).live()

  with raises(SuccessError):
    for b in range(2):
      testBlockchain(b)
Пример #25
0
#Add a 5th Block to another verifier.
block: Block = Block(
    BlockHeader(0, merit.blockchain.last(), bytes(32), 1, bytes(4), bytes(32),
                blsPubKeys[1].serialize(),
                merit.blockchain.blocks[-1].header.time + 1200), BlockBody())
#Mine it.
block.mine(blsPrivKeys[1], merit.blockchain.difficulty())

#Add it.
merit.add(block)
print("Generated Aggregated Claim Block " +
      str(len(merit.blockchain.blocks) - 1) + ".")

#Create the Datas.
datas: List[Data] = [Data(bytes(32), edPubKey.to_bytes())]
datas.append(Data(datas[-1].hash, bytes(1)))
datas.append(Data(datas[-1].hash, bytes(1)))
datas.append(Data(datas[-1].hash, bytes(1)))
for data in datas:
    data.sign(edPrivKey)
    data.beat(dataFilter)
    transactions.add(data)

#Verify them.
verifs: List[List[SignedVerification]] = []
for data in datas:
    verifs.append(
        [SignedVerification(data.hash),
         SignedVerification(data.hash)])
    for v in range(2):
Пример #26
0
from e2e.Classes.Consensus.Verification import SignedVerification
from e2e.Classes.Consensus.VerificationPacket import VerificationPacket
from e2e.Classes.Consensus.SpamFilter import SpamFilter

from e2e.Vectors.Generation.PrototypeChain import PrototypeChain

dataFilter: SpamFilter = SpamFilter(5)

edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
edPubKey: bytes = edPrivKey.get_verifying_key()

proto: PrototypeChain = PrototypeChain(40, keepUnlocked=True)
proto.add(1)

datas: List[Data] = [Data(bytes(32), edPubKey)]
for d in range(2):
  datas.append(Data(datas[0].hash, d.to_bytes(1, "little")))
for data in datas:
  data.sign(edPrivKey)
  data.beat(dataFilter)

verif: SignedVerification = SignedVerification(datas[1].hash)
verif.sign(0, PrivateKey(0))
proto.add(
  packets=[
    VerificationPacket(datas[0].hash, [0]),
    VerificationPacket(datas[2].hash, [1])
  ]
)
Пример #27
0
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()
Пример #28
0
    def finish(self, keepUnlocked: int, existing: Merit) -> Block:
        genesis: bytes = existing.blockchain.genesis
        prev: BlockHeader = existing.blockchain.blocks[-1].header
        diff: int = existing.blockchain.difficulty()

        #Create the signatures for every packet/element.
        signatures: List[Signature] = []
        for packet in self.packets:
            for holder in packet.holders:
                verif: SignedVerification = SignedVerification(
                    packet.hash, holder)
                verif.sign(holder, PrivateKey(holder))
                signatures.append(verif.signature)
        for element in self.elements:
            signatures.append(signElement(element))

        #Only add the Data Verification if:
        #1) We're supposed to make sure Merit Holders are always Unlocked
        #2) The last Block created a Data
        #3) The Merit Holder has Merit.
        if (keepUnlocked != 0) and (prev.last != genesis):
            #Create the Data from the last Block.
            blockData: Data = Data(genesis, prev.hash)

            #Create Verifications for said Data with every Private Key.
            #Ensures no one has their Merit locked.
            #pylint: disable=unnecessary-comprehension
            self.packets.append(VerificationPacket(blockData.hash, []))
            for i in range(keepUnlocked):
                if (
                        #Miners who are just being created don't have Merit.
                    ((i == (keepUnlocked - 1)) and
                     (isinstance(self.minerID, PrivateKey)))
                        or (existing.state.balances[i] == 0)):
                    continue

                self.packets[-1].holders.append(i)
                verif: SignedVerification = SignedVerification(
                    blockData.hash, i)
                verif.sign(i, PrivateKey(i))
                signatures.append(verif.signature)

            #Remove this packet if there's no holders.
            if not self.packets[-1].holders:
                del self.packets[-1]

        #Set the aggregate.
        aggregate = Signature.aggregate(signatures)

        #Create the actual Block.
        minerID: Union[bytes, int] = 0
        if isinstance(self.minerID, int):
            minerID = self.minerID
        else:
            minerID = self.minerID.toPublicKey().serialize()

        result: Block = Block(
            BlockHeader(
                0, prev.hash,
                BlockHeader.createContents(self.packets, self.elements),
                len(self.packets), bytes(4),
                BlockHeader.createSketchCheck(bytes(4), self.packets), minerID,
                self.time), BlockBody(self.packets, self.elements, aggregate))
        if isinstance(self.minerID, int):
            result.mine(PrivateKey(self.minerID), diff)
        else:
            result.mine(self.minerID, diff)
        return result
Пример #29
0
def StringBasedTypesTest(
  rpc: RPC
) -> None:
  edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
  edPubKey: bytes = edPrivKey.get_verifying_key()
  blsPubKey: PublicKey = PrivateKey(0).toPublicKey()

  #hex.
  #Test 0x-prefixed and no-0x both work without issue.
  data: Data = Data(bytes(32), edPubKey)
  data.sign(edPrivKey)
  rpc.call("transactions", "publishTransactionWithoutWork", {"type": "Data", "transaction": "0x" + data.serialize()[:-4].hex()})

  data = Data(data.hash, b"abc")
  data.sign(edPrivKey)
  rpc.call("transactions", "publishTransactionWithoutWork", {"type": "Data", "transaction": data.serialize()[:-4].hex()})

  #Test non-hex data is properly handled.
  try:
    rpc.call("transactions", "publishTransactionWithoutWork", {"type": "Data", "transaction": "az"})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted non-hex data for a hex argument.")

  #Hash.
  rpc.call("transactions", "getTransaction", {"hash": data.hash.hex()})
  rpc.call("transactions", "getTransaction", {"hash": "0x" + data.hash.hex()})

  #Also call the upper form, supplementing the above hex tests (as Hash routes through hex).
  rpc.call("transactions", "getTransaction", {"hash": data.hash.hex().upper()})
  rpc.call("transactions", "getTransaction", {"hash": "0x" + data.hash.hex().upper()})

  #Improper length.
  try:
    rpc.call("transactions", "getTransaction", {"hash": data.hash.hex().upper()[:-2]})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted a hex string with an improper length as a Hash.")

  #BLSPublicKey.
  try:
    rpc.call("merit", "getNickname", {"key": blsPubKey.serialize().hex()})
    raise TestError()
  except Exception as e:
    if str(e) != "-2 Key doesn't have a nickname assigned.":
      raise TestError("Meros didn't accept a valid BLSPublicKey.")
  try:
    rpc.call("merit", "getNickname", {"key": blsPubKey.serialize().hex()[:-2]})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted a hex string with an improper length as a BLSPublicKey.")

  #Missing flags.
  try:
    rpc.call("merit", "getNickname", {"key": "0" + blsPubKey.serialize().hex()[1]})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted an invalid BLSPublicKey as a BLSPublicKey.")

  #EdPublicKey.
  rpc.call("personal", "setAccount", {"key": edPubKey.hex(), "chainCode": bytes(32).hex()})
  try:
    rpc.call("personal", "setAccount", {"key": edPubKey[:-2].hex(), "chainCode": bytes(32).hex()})
    raise TestError()
  except Exception as e:
    if str(e) != "-32602 Invalid params.":
      raise TestError("Meros accepted a hex string with an improper length as an EdPublicKey.")
Пример #30
0
from e2e.Classes.Transactions.Data import Data
from e2e.Classes.Consensus.Verification import SignedVerification
from e2e.Classes.Consensus.VerificationPacket import VerificationPacket
from e2e.Classes.Consensus.SpamFilter import SpamFilter

from e2e.Vectors.Generation.PrototypeChain import PrototypeChain

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

spamFilter: SpamFilter = SpamFilter(5)

proto: PrototypeChain = PrototypeChain(1, keepUnlocked=False)

data: Data = Data(bytes(32), pubKey.to_bytes())
datas: List[Dict[str, Any]] = []
verifs: List[Dict[str, Any]] = []
for i in range(5):
  data.sign(privKey)
  data.beat(spamFilter)
  datas.append(data.toJSON())

  if i != 4:
    verif: SignedVerification = SignedVerification(data.hash)
    verif.sign(0, PrivateKey(0))
    verifs.append(verif.toSignedJSON())
    data = Data(data.hash, bytes(1))

proto.add(0, [VerificationPacket(bytes.fromhex(data["hash"]), [0]) for data in datas])