Пример #1
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.")
Пример #2
0
    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."
        )
Пример #3
0
 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.")
Пример #4
0
 def hash(
   sketchSalt: bytes,
   packet: VerificationPacket
 ) -> int:
   return int.from_bytes(
     blake2b(sketchSalt + packet.serialize(), digest_size=8).digest(),
     byteorder="little"
   )
Пример #5
0
 def packet(
   self,
   packet: VerificationPacket
 ) -> bytes:
   res: bytes = (
     MessageType.VerificationPacket.toByte() +
     packet.serialize()
   )
   self.sync.send(res)
   return res
Пример #6
0
  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.")
Пример #7
0
    def fromJSON(json: Dict[str, Any]) -> Any:
        packets: List[VerificationPacket] = []
        elements: List[Element] = []

        for packet in json["transactions"]:
            packets.append(
                VerificationPacket(bytes.fromhex(packet["hash"]),
                                   packet["holders"]))

        for element in json["elements"]:
            if element["descendant"] == "SendDifficulty":
                elements.append(SendDifficulty.fromJSON(element))
            elif element["descendant"] == "DataDifficulty":
                elements.append(DataDifficulty.fromJSON(element))

        return BlockBody(packets, elements,
                         Signature(bytes.fromhex(json["aggregate"])))
Пример #8
0
proto: PrototypeChain = PrototypeChain(1, keepUnlocked=False)

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

proto.add(packets=[
    VerificationPacket(first.hash, [0]),
    VerificationPacket(second.hash, [0])
])

for _ in range(5):
    proto.add()

#Create a Data competing with the now-finalized second Data.
competitor: Data = Data(first.hash, bytes(2))
competitor.sign(edPrivKey)
competitor.beat(dataFilter)
transactions.add(competitor)

proto.add(packets=[VerificationPacket(competitor.hash, [0])])

with open("e2e/Vectors/Transactions/CompetingFinalized.json", "w") as vectors:
Пример #9
0
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])

with open("e2e/Vectors/Merit/Sketches/MissingOne.json", "w") as vectors:
  vectors.write(
    json.dumps({
      "blockchain": proto.toJSON(),
      "datas": datas,
      "verifications": verifs,
      "packet": VerificationPacket(data.hash, [0]).toJSON()
    })
  )
Пример #10
0
edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
edPubKey: bytes = edPrivKey.get_verifying_key()

transactions: Transactions = Transactions()
spamFilter: SpamFilter = SpamFilter(5)

proto = PrototypeChain(1, False)
proto.add(1)

data: Data = Data(bytes(32), edPubKey)
data.sign(edPrivKey)
data.beat(spamFilter)
transactions.add(data)

verif: SignedVerification = SignedVerification(data.hash)
verif.sign(1, PrivateKey(1))

proto.add(1, packets=[VerificationPacket(data.hash, [0])])
for _ in range(5):
    proto.add(1)

with open("e2e/Vectors/Consensus/Verification/HundredFortyTwo.json",
          "w") as vectors:
    vectors.write(
        json.dumps({
            "blockchain": proto.toJSON(),
            "transactions": transactions.toJSON(),
            "verification": verif.toSignedJSON(),
            "transaction": data.hash.hex().upper()
        }))
Пример #11
0
transactions: Transactions = Transactions()

dataFilter: SpamFilter = SpamFilter(5)

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

blsPrivKey: PrivateKey = PrivateKey(0)

#Generate a Data to verify for the VerificationPacket Block.
data: Data = Data(bytes(32), edPubKey)
data.sign(edPrivKey)
data.beat(dataFilter)
transactions.add(data)
packet: VerificationPacket = VerificationPacket(data.hash, [1])

blocks.append(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(data.hash, [1])],
                   minerID=blsPrivKey).finish(0, merit).toJSON())

#Generate the SendDifficulty Block.
blocks.append(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   elements=[SendDifficulty(0, 0, 1)],
                   minerID=blsPrivKey).finish(0, merit).toJSON())

#Generate the DataDifficulty Block.
blocks.append(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
Пример #12
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
Пример #13
0
  merit.add(Block.fromJSON(blankBlocks[i]))

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

#Verify them in unique Blocks.
packet: List[VerificationPacket]
for data in datas:
  verif: SignedVerification = SignedVerification(data.hash)
  verif.sign(0, blsPrivKey)
  packet = [VerificationPacket(data.hash, [0])]

  block = Block(
    BlockHeader(
      0,
      merit.blockchain.last(),
      BlockHeader.createContents(packet),
      1,
      bytes(4),
      BlockHeader.createSketchCheck(bytes(4), packet),
      0,
      merit.blockchain.blocks[-1].header.time + 1200
    ),
    BlockBody(packet, [], verif.signature)
  )
  block.mine(blsPrivKey, merit.blockchain.difficulty())
Пример #14
0
datas: List[Data] = [
    Data(bytes(32),
         ed25519.SigningKey(b'\0' * 32).get_verifying_key().to_bytes())
]
for _ in range(4):
    datas[-1].sign(ed25519.SigningKey(b'\0' * 32))
    datas[-1].beat(SpamFilter(5))
    transactions.add(datas[-1])
    datas.append(Data(datas[-1].hash, b'\0'))
del datas[-1]

merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[
                       VerificationPacket(claim.hash, [0]),
                       VerificationPacket(send.hash, [0, 1, 2]),
                       VerificationPacket(datas[0].hash, [0, 2]),
                       VerificationPacket(datas[1].hash, [0, 1, 3]),
                       VerificationPacket(datas[2].hash, [0, 1, 2, 3, 4]),
                       VerificationPacket(datas[3].hash, [0, 1, 2, 3])
                   ],
                   elements=[
                       DataDifficulty(8, 0, 3),
                       SendDifficulty(1, 0, 0),
                       DataDifficulty(4, 0, 3),
                       DataDifficulty(1, 2, 4),
                       SendDifficulty(3, 1, 4),
                       SendDifficulty(2, 1, 2),
                       DataDifficulty(7, 0, 0),
                   ]).finish(0, merit))
Пример #15
0
blockchain.add(block)
print("Generated Hundred Forty Two Block " + str(len(blockchain.blocks)) + ".")

#Create a Data and verify it by both parties.
data: Data = Data(bytes(32), edPubKey.to_bytes())
data.sign(edPrivKey)
data.beat(spamFilter)
transactions.add(data)

verifs: List[SignedVerification] = [
    SignedVerification(data.hash),
    SignedVerification(data.hash)
]
verifs[0].sign(0, blsPrivKeys[0])
verifs[1].sign(1, blsPrivKeys[1])
packets: List[VerificationPacket] = [VerificationPacket(data.hash, [0])]

block = Block(
    BlockHeader(0, blockchain.last(), BlockHeader.createContents(packets), 1,
                bytes(4), BlockHeader.createSketchCheck(bytes(4), packets), 1,
                blockchain.blocks[-1].header.time + 1200),
    BlockBody(packets, [], verifs[0].signature))
for _ in range(6):
    block.mine(blsPrivKeys[1], blockchain.difficulty())
    blockchain.add(block)
    print("Generated Hundred Forty Two Block " + str(len(blockchain.blocks)) +
          ".")

    #Create the next Block.
    block = Block(
        BlockHeader(0, blockchain.last(), bytes(32), 1, bytes(4), bytes(32), 1,
Пример #16
0
    ed25519.SigningKey(b'\1' * 32).get_verifying_key()
]

sendFilter: SpamFilter = SpamFilter(3)

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

#Create the Claim.
claim: Claim = Claim([(merit.mints[-1].hash, 0)], edPubKeys[0].to_bytes())
claim.amount = merit.mints[-1].outputs[0][1]
claim.sign(PrivateKey(0))
transactions.add(claim)
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(claim.hash,
                                               [0])]).finish(0, merit))

#Create 12 Sends.
sends: List[Send] = []
sends.append(Send([(claim.hash, 0)], [(edPubKey.to_bytes(), claim.amount)]))
for _ in range(12):
    sends[-1].sign(edPrivKey)
    sends[-1].beat(sendFilter)
    transactions.add(sends[-1])

    sends.append(
        Send([(sends[-1].hash, 0)],
             [(edPubKey.to_bytes(), sends[-1].outputs[0][1])]))

#Order to verify the Transactions in.
#Dict key is holder nick.
Пример #17
0
#Create a Claim and a Send splitting its outputs.
claim: Claim = Claim([(merit.mints[-1], 0)], edPubKey)
claim.sign(PrivateKey(0))
transactions.add(claim)

splitSend: Send = Send([(claim.hash, 0)], [(edPubKey, claim.amount // 2) for _ in range(2)])
splitSend.sign(edPrivKey)
splitSend.beat(sendFilter)
transactions.add(splitSend)

merit.add(
  PrototypeBlock(
    merit.blockchain.blocks[-1].header.time + 1200,
    packets=[
      VerificationPacket(claim.hash, list(range(5))),
      VerificationPacket(splitSend.hash, list(range(5)))
    ]
  ).finish(5, merit)
)

#We need to define two families. Family A (send output 0) and family B (send output 1).
sends: List[Send] = [
  #A.
  Send([(splitSend.hash, 0)], [(edPubKey, claim.amount // 2)]),
  Send([(splitSend.hash, 0)], [(bytes(32), claim.amount // 2)]),
  #B.
  Send([(splitSend.hash, 1)], [(edPubKey, claim.amount // 2)]),
  Send([(splitSend.hash, 1)], [(bytes(32), claim.amount // 2)]),
  #Now, union them.
  Send([(splitSend.hash, 0), (splitSend.hash, 1)], [(edPubKey, claim.amount)]),
Пример #18
0
import ed25519

from e2e.Classes.Transactions.Data import Data
from e2e.Classes.Consensus.VerificationPacket import VerificationPacket
from e2e.Classes.Consensus.SpamFilter import SpamFilter

from e2e.Vectors.Generation.PrototypeChain import PrototypeChain

#Generate a chain with 2 Merit Holders.
proto: PrototypeChain = PrototypeChain(1)
proto.add(1)

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

#Create a Data.
data: Data = Data(bytes(32), edPubKey.to_bytes())
data.sign(edPrivKey)
data.beat(SpamFilter(5))
proto.add(packets=[
    VerificationPacket(data.hash, [0]),
    VerificationPacket(data.hash, [1])
])

with open("e2e/Vectors/Merit/MultiplePackets.json", "w") as vectors:
    vectors.write(
        json.dumps({
            "blockchain": proto.toJSON(),
            "data": data.toJSON()
        }))
Пример #19
0
def getBlockTemplateTest(rpc: RPC) -> None:
    edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32)
    edPubKey: bytes = edPrivKey.get_verifying_key()
    blockchain: Blockchain = Blockchain()

    #Get multiple templates to verify they share an ID if they're requested within the same second.
    templates: List[Dict[str, Any]] = []
    startTime: float = nextSecond()
    for k in range(5):
        templates.append(
            rpc.call("merit", "getBlockTemplate", {"miner": getMiner(k)},
                     False))
    if int(startTime) != int(time.time()):
        #Testing https://github.com/MerosCrypto/Meros/issues/278 has a much more forgiving timer of < 1 second each.
        #That said, this test was written on the fair assumption of all the above taking place in a single second.
        raise Exception(
            "getBlockTemplate is incredibly slow, to the point an empty Block template takes > 0.2 seconds to grab, invalidating this test."
        )

    for k, template in zip(range(5), templates):
        if template["id"] != int(startTime):
            raise TestError("Template ID isn't the time.")

        #Also check general accuracy.
        if bytes.fromhex(template["key"]) != blockchain.genesis:
            raise TestError("Template has the wrong RandomX key.")

        bytesHeader: bytes = bytes.fromhex(template["header"])
        serializedHeader: bytes = BlockHeader(
            0, blockchain.blocks[0].header.hash, bytes(32), 0, bytes(4),
            bytes(32),
            PrivateKey(k).toPublicKey().serialize(),
            int(startTime)).serialize()[:-52]
        #Skip over the randomized sketch salt.
        if (bytesHeader[:72] + bytesHeader[76:]) != (serializedHeader[:72] +
                                                     serializedHeader[76:]):
            raise TestError("Template has an invalid header.")
        #Difficulty modified as this is a new miner.
        if template["difficulty"] != (blockchain.difficulty() * 11 // 10):
            raise TestError("Template's difficulty is wrong.")

    currTime: int = int(nextSecond())
    template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate",
                                        {"miner": getMiner(0)}, False)
    if template["id"] != currTime:
        raise TestError("Template ID wasn't advanced with the time.")

    #Override the ID to enable easy comparison against a historical template.
    template["id"] = int(startTime)

    if int.from_bytes(bytes.fromhex(template["header"])[-4:],
                      "little") != currTime:
        raise TestError("The header has the wrong time.")
    template["header"] = (
        bytes.fromhex(template["header"])[:72] +
        #Use the header we'll compare to's salt.
        bytes.fromhex(templates[0]["header"])[72:76] +
        bytes.fromhex(template["header"])[76:-4] +
        #Also use its time.
        int(startTime).to_bytes(4, "little")).hex().upper()

    if template != templates[0]:
        raise TestError(
            "Template, minus the time difference, doesn't match the originally provided template."
        )

    #Test that the templates are deleted whenever a new Block appears.
    #This is done by checking the error given when we use an old template.
    with open("e2e/Vectors/Merit/BlankBlocks.json", "r") as file:
        block: Block = Block.fromJSON(json.loads(file.read())[0])
        blockchain.add(block)
        rpc.meros.liveConnect(blockchain.blocks[0].header.hash)
        rpc.meros.syncConnect(blockchain.blocks[0].header.hash)
        rpc.meros.liveBlockHeader(block.header)
        rpc.meros.rawBlockBody(block, 0)
        time.sleep(1)
    #Sanity check.
    if rpc.call("merit", "getHeight", auth=False) != 2:
        raise Exception("Didn't successfully send Meros the Block.")

    #Get a new template so Meros realizes the template situation has changed.
    rpc.call("merit", "getBlockTemplate", {"miner": getMiner(0)}, False)

    try:
        rpc.call("merit", "publishBlock", {
            "id": int(startTime),
            "header": ""
        }, False)
        raise Exception("")
    except Exception as e:
        if str(e) != "-2 Invalid ID.":
            raise TestError("Meros didn't delete old template IDs.")

    #Test VerificationPacket inclusion.
    data: Data = Data(bytes(32), edPubKey)
    data.sign(edPrivKey)
    data.beat(SpamFilter(5))
    verif: SignedVerification = SignedVerification(data.hash)
    verif.sign(0, PrivateKey(0))
    packet = VerificationPacket(data.hash, [0])

    rpc.meros.liveTransaction(data)
    rpc.meros.signedElement(verif)
    time.sleep(1)
    if bytes.fromhex(
            rpc.call("merit", "getBlockTemplate", {"miner": getMiner(0)},
                     False)["header"])[36:68] != BlockHeader.createContents(
                         [packet]):
        raise TestError(
            "Meros didn't include the Verification in its new template.")

    #Test Element inclusion.
    sendDiff: SignedSendDifficulty = SignedSendDifficulty(0, 0)
    sendDiff.sign(0, PrivateKey(0))
    rpc.meros.signedElement(sendDiff)
    time.sleep(1)
    if bytes.fromhex(
            rpc.call("merit", "getBlockTemplate", {"miner": getMiner(0)},
                     False)["header"])[36:68] != BlockHeader.createContents(
                         [packet], [sendDiff]):
        raise TestError(
            "Meros didn't include the Element in its new template.")

    #The 88 test checks for the non-inclusion of Verifications with unmentioned predecessors.
    #Test for non-inclusion of Elements with unmentioned predecessors.
    sendDiffChild: SignedSendDifficulty = SignedSendDifficulty(0, 2)
    sendDiffChild.sign(0, PrivateKey(0))
    rpc.meros.signedElement(sendDiffChild)
    time.sleep(1)
    if bytes.fromhex(
            rpc.call("merit", "getBlockTemplate", {"miner": getMiner(0)},
                     False)["header"])[36:68] != BlockHeader.createContents(
                         [packet], [sendDiff]):
        raise TestError(
            "Meros did include an Element with an unmentioned parent in its new template."
        )

    #If we send a block with a time in the future, yet within FTL (of course), make sure Meros can still generate a template.
    #Naively using the current time will create a negative clock, which isn't allowed.
    #Start by closing the sockets to give us time to work.
    rpc.meros.live.connection.close()
    rpc.meros.sync.connection.close()
    #Sleep to reset the connection state.
    time.sleep(35)

    #Create and mine the Block.
    header: BlockHeader = BlockHeader(
        0,
        blockchain.blocks[-1].header.hash,
        bytes(32),
        0,
        bytes(4),
        bytes(32),
        PrivateKey(0).toPublicKey().serialize(),
        0,
    )
    miningStart: int = 0
    #If this block takes longer than 10 seconds to mine, try another.
    #Low future time (20 seconds) is chosen due to feasibility + supporting lowering the FTL in the future.
    while time.time() > miningStart + 10:
        miningStart = int(time.time())
        header = BlockHeader(
            0,
            blockchain.blocks[-1].header.hash,
            bytes(32),
            0,
            bytes(4),
            bytes(32),
            #Mod by something is due to a 2-byte limit (IIRC -- Kayaba).
            #100 is just clean. +11 ensures an offset from the above, which really shouldn't be necessary.
            #If we did need one, +1 should work, as we only ever work with PrivateKey(0) on the blockchain.
            PrivateKey((miningStart % 100) + 10).toPublicKey().serialize(),
            int(time.time()) + 20,
        )
        header.mine(PrivateKey((miningStart % 100) + 10),
                    blockchain.difficulty() * 11 // 10)
    blockchain.add(Block(header, BlockBody()))

    #Send it and verify it.
    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)
    rpc.meros.syncConnect(blockchain.blocks[0].header.hash)
    rpc.meros.liveBlockHeader(header)
    rpc.meros.rawBlockBody(Block(header, BlockBody()), 0)
    rpc.meros.live.connection.close()
    rpc.meros.sync.connection.close()
    time.sleep(1)

    #Ensure a stable template ID.
    currTime = int(nextSecond())
    template = rpc.call("merit", "getBlockTemplate", {"miner": getMiner(0)},
                        False)
    if template["id"] != currTime:
        raise TestError(
            "Template ID isn't the time when the previous Block is in the future."
        )
    if int.from_bytes(bytes.fromhex(template["header"])[-4:],
                      "little") != (header.time + 1):
        raise TestError(
            "Meros didn't handle generating a template off a Block in the future properly."
        )

    #Verify a Block with three Elements from a holder, where two form a Merit Removal.
    #Only the two which cause a MeritRemoval should be included.
    #Mine a Block to a new miner and clear the current template with it (might as well).
    #Also allows us to test template clearing.
    template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate",
                                        {"miner": getMiner(1)}, False)
    #Mine the Block.
    proof: int = -1
    tempHash: bytes = bytes()
    tempSignature: bytes = bytes()
    while ((proof == -1)
           or ((int.from_bytes(tempHash, "little") *
                (blockchain.difficulty() * 11 // 10)) > int.from_bytes(
                    bytes.fromhex("FF" * 32), "little"))):
        proof += 1
        tempHash = RandomX(
            bytes.fromhex(template["header"]) + proof.to_bytes(4, "little"))
        tempSignature = PrivateKey(1).sign(tempHash).serialize()
        tempHash = RandomX(tempHash + tempSignature)
    rpc.call(
        "merit", "publishBlock", {
            "id":
            template["id"],
            "header":
            template["header"] + proof.to_bytes(4, "little").hex() +
            tempSignature.hex()
        })
    time.sleep(1)

    #Verify the template was cleared.
    currTime = int(nextSecond())
    bytesHeader: bytes = bytes.fromhex(
        rpc.call("merit", "getBlockTemplate", {"miner": getMiner(0)},
                 False)["header"])
    serializedHeader: bytes = BlockHeader(
        0,
        tempHash,
        bytes(32),
        0,
        bytes(4),
        bytes(32),
        0,
        #Ensures that the previous time manipulation doesn't come back to haunt us.
        max(currTime, blockchain.blocks[-1].header.time + 1)).serialize()[:-52]
    #Skip over the randomized sketch salt and time (which we don't currently have easy access to).
    if (bytesHeader[:72] + bytesHeader[76:-4]) != (serializedHeader[:72] +
                                                   serializedHeader[76:-4]):
        raise TestError("Template wasn't cleared.")

    #Sleep so we can reconnect.
    time.sleep(35)
    rpc.meros.liveConnect(blockchain.blocks[0].header.hash)

    #Finally create the Elements.
    dataDiff: SignedDataDifficulty = SignedDataDifficulty(1, 0)
    dataDiff.sign(2, PrivateKey(1))
    rpc.meros.signedElement(dataDiff)
    sendDiffs: List[SignedSendDifficulty] = [
        SignedSendDifficulty(1, 1),
        SignedSendDifficulty(2, 1)
    ]
    for sd in sendDiffs:
        sd.sign(2, PrivateKey(1))
        rpc.meros.signedElement(sd)
    time.sleep(1)

    #`elem for elem` is used below due to Pyright not handling inheritance properly when nested.
    #pylint: disable=unnecessary-comprehension
    if bytes.fromhex(
            rpc.call("merit", "getBlockTemplate", {"miner": getMiner(0)},
                     False)["header"])[36:68] != BlockHeader.createContents(
                         [], [elem for elem in sendDiffs[::-1]]):
        raise TestError(
            "Meros didn't include just the malicious Elements in its new template."
        )
Пример #20
0
transactions: Transactions = Transactions()
sendFilter: SpamFilter = SpamFilter(3)

proto: PrototypeChain = PrototypeChain(40, keepUnlocked=True)
proto.add(1)
merit: Merit = Merit.fromJSON(proto.toJSON())

#Create a Claim.
claim: Claim = Claim([(merit.mints[-1], 0)], edPubKey)
claim.sign(PrivateKey(0))
transactions.add(claim)

merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(claim.hash, list(range(2)))
                            ]).finish(2, merit))

sends: List[Send] = [Send([(claim.hash, 0)], [(edPubKey, claim.amount)])]
sends.append(
    Send([(claim.hash, 0), (sends[0].hash, 0)],
         [(edPubKey, claim.amount * 2)]))

for send in sends:
    send.sign(edPrivKey)
    send.beat(sendFilter)
    transactions.add(send)

#Verify the 'impossible' TX, mentioning the only possible one.
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
Пример #21
0
from e2e.Classes.Merit.Merit import Merit

from e2e.Vectors.Generation.PrototypeChain import PrototypeBlock, PrototypeChain

edPubKey: bytes = ed25519.SigningKey(b'\0' * 32).get_verifying_key().to_bytes()

proto: PrototypeChain = PrototypeChain(49, keepUnlocked=True)
merit: Merit = Merit.fromJSON(proto.toJSON())

transactions: Transactions = Transactions()

#Create the Claims.
for m in range(3):
    claim: Claim = Claim([(merit.mints[m], 0)], edPubKey)
    claim.sign(PrivateKey(0))
    transactions.add(claim)

merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[
                       VerificationPacket(tx.hash, [0])
                       for tx in transactions.txs.values()
                   ]).finish(0, merit))

with open("e2e/Vectors/RPC/Personal/WatchWallet.json", "w") as vectors:
    vectors.write(
        json.dumps({
            "blockchain": merit.toJSON(),
            "transactions": transactions.toJSON()
        }))
Пример #22
0
transactions: Transactions = Transactions()
sendFilter: SpamFilter = SpamFilter(3)

proto: PrototypeChain = PrototypeChain(40, keepUnlocked=True)
proto.add(1)
merit: Merit = Merit.fromJSON(proto.toJSON())

#Create a Claim.
claim: Claim = Claim([(merit.mints[-1], 0)], edPubKey)
claim.sign(PrivateKey(0))
transactions.add(claim)

merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(claim.hash, list(range(2)))
                            ]).finish(0, merit))

sends: List[Send] = [
    #Transaction which will win.
    Send([(claim.hash, 0)], [(bytes(32), claim.amount)]),
    #Transaction which will be beaten.
    Send([(claim.hash, 0)], [(edPubKey, claim.amount // 2),
                             (edPubKey, claim.amount // 2)])
]
#Children. One which will have a Verification, one which won't.
sends += [
    Send([(sends[1].hash, 0)], [(edPubKey, claim.amount // 2)]),
    Send([(sends[1].hash, 1)], [(edPubKey, claim.amount // 2)])
]
Пример #23
0
edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key()

proto: PrototypeChain = PrototypeChain(5)
for _ in range(80):
    proto.add(1)

for _ in range(14):
    proto.add(2)

data: Data = Data(bytes(32), edPubKey.to_bytes())
data.sign(edPrivKey)
data.beat(spamFilter)
transactions.add(data)

proto.add(2, [VerificationPacket(data.hash, [0, 1])])

#Close out the Epoch.
for _ in range(6):
    proto.add(2)

vectors: IO[Any] = open("e2e/Vectors/Consensus/Verification/HundredTwo.json",
                        "w")
vectors.write(
    json.dumps({
        "blockchain": proto.toJSON(),
        "transactions": transactions.toJSON()
    }))
vectors.close()
Пример #24
0
#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),
        BlockHeader.createSketchCheck(bytes(4),
                                      [VerificationPacket(verif.hash, [0])]),
        0, merit.blockchain.blocks[-1].header.time + 1200),
    BlockBody([VerificationPacket(verif.hash, [0])], [], verif.signature))
for _ in range(6):
    #Mine it.
    block.mine(blsPrivKey, merit.blockchain.difficulty())

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

    #Create the next Block.
Пример #25
0
from e2e.Classes.Transactions.Transactions import Transactions

from e2e.Classes.Consensus.VerificationPacket import VerificationPacket

from e2e.Classes.Merit.Merit import Merit

from e2e.Vectors.Generation.PrototypeChain import PrototypeBlock, PrototypeChain

merit: Merit = PrototypeChain.withMint()
transactions: Transactions = Transactions()

claim: Claim = Claim([(merit.mints[-1].hash, 0)],
                     ed25519.SigningKey(b'\0' *
                                        32).get_verifying_key().to_bytes())
claim.amount = merit.mints[-1].outputs[0][1]
claim.sign(PrivateKey(0))
transactions.add(claim)

merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(claim.hash,
                                               [0])]).finish(0, merit))

result: Dict[str, Any] = {
    "blockchain": merit.toJSON(),
    "transactions": transactions.toJSON()
}
vectors: IO[Any] = open("e2e/Vectors/Transactions/ClaimedMint.json", "w")
vectors.write(json.dumps(result))
vectors.close()
Пример #26
0
from e2e.Classes.Transactions.Data import Data
from e2e.Classes.Transactions.Transactions import Transactions

from e2e.Classes.Consensus.VerificationPacket import VerificationPacket

from e2e.Vectors.Generation.PrototypeChain import PrototypeChain

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

proto: PrototypeChain = PrototypeChain(1, keepUnlocked=False)
datas: List[Data] = [Data(bytes(32), edPubKey)]

counter: int = 0
datas.append(Data(datas[0].hash, counter.to_bytes(4, byteorder="little")))
while (Sketch.hash(bytes(4), VerificationPacket(datas[0].hash, [0])) <=
       Sketch.hash(bytes(4), VerificationPacket(datas[1].hash, [0]))):
    counter += 1
    datas[1] = Data(datas[0].hash, counter.to_bytes(4, byteorder="little"))

proto.add(packets=[
    VerificationPacket(datas[1].hash, [0]),
    VerificationPacket(datas[0].hash, [0])
])

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

with open("e2e/Vectors/Merit/OutOfOrder/Packets.json", "w") as vectors:
Пример #27
0
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])
  ]
)

for _ in range(5):
  proto.add()

with open("e2e/Vectors/Consensus/Families/UnmentionedBeatMentioned.json", "w") as vectors:
  vectors.write(json.dumps({
    "blockchain": proto.toJSON(),
    "datas": [data.toJSON() for data in datas],
    "verification": verif.toSignedJSON()
  }))
Пример #28
0
def EightyEightTest(
  rpc: RPC
) -> None:
  edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
  edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key()

  blsPrivKey: PrivateKey = PrivateKey(0)
  blsPubKey: str = blsPrivKey.toPublicKey().serialize().hex()

  file: IO[Any] = open("e2e/Vectors/Merit/BlankBlocks.json", "r")
  blocks: List[Dict[str, Any]] = json.loads(file.read())
  file.close()

  merit: Merit = Merit()
  dataFilter: SpamFilter = SpamFilter(5)

  #Handshake with the node.
  rpc.meros.liveConnect(merit.blockchain.blocks[0].header.hash)
  rpc.meros.syncConnect(merit.blockchain.blocks[0].header.hash)

  #Send the first Block.
  block: Block = Block.fromJSON(blocks[0])
  merit.blockchain.add(block)
  rpc.meros.liveBlockHeader(block.header)

  #Handle sync requests.
  reqHash: bytes = bytes()
  while True:
    msg: bytes = rpc.meros.sync.recv()
    if MessageType(msg[0]) == MessageType.BlockBodyRequest:
      reqHash = msg[1 : 33]
      if reqHash != block.header.hash:
        raise TestError("Meros asked for a Block Body that didn't belong to the Block we just sent it.")

      #Send the BlockBody.
      rpc.meros.blockBody(block)
      break

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

  if MessageType(rpc.meros.live.recv()[0]) != MessageType.BlockHeader:
    raise TestError("Meros didn't broadcast the Block Header it just added.")

  #Create two Datas.
  datas: List[Data] = [Data(bytes(32), edPubKey.to_bytes())]
  datas.append(Data(datas[0].hash, b"Hello there! General Kenobi."))

  for data in datas:
    #Sign them and have them beat the spam filter.
    data.sign(edPrivKey)
    data.beat(dataFilter)

    #Transmit them.
    rpc.meros.liveTransaction(data)

  #Verify both.
  verifs: List[SignedVerification] = [
    SignedVerification(datas[0].hash),
    SignedVerification(datas[1].hash)
  ]
  for verif in verifs:
    verif.sign(0, blsPrivKey)

  #Only transmit the second.
  rpc.meros.signedElement(verifs[1])
  sleep(0.5)

  #Verify the block template has no verifications.
  if bytes.fromhex(
    rpc.call("merit", "getBlockTemplate", [blsPubKey])["header"]
  )[36 : 68] != bytes(32):
    raise TestError("Block template has Verification Packets.")

  #Transmit the first signed verification.
  rpc.meros.signedElement(verifs[0])
  sleep(0.5)

  #Verify the block template has both verifications.
  template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate", [blsPubKey])
  template["header"] = bytes.fromhex(template["header"])
  packets: List[VerificationPacket] = [VerificationPacket(datas[0].hash, [0]), VerificationPacket(datas[1].hash, [0])]
  if template["header"][36 : 68] != BlockHeader.createContents(packets):
    raise TestError("Block template doesn't have both Verification Packets.")

  #Mine the Block.
  block = Block(
    BlockHeader(
      0,
      block.header.hash,
      BlockHeader.createContents(packets),
      1,
      template["header"][-43 : -39],
      BlockHeader.createSketchCheck(template["header"][-43 : -39], packets),
      0,
      int.from_bytes(template["header"][-4:], byteorder="little")
    ),
    BlockBody(
      packets,
      [],
      Signature.aggregate([verifs[0].signature, verifs[1].signature])
    )
  )
  if block.header.serializeHash()[:-4] != template["header"]:
    raise TestError("Failed to recreate the header.")
  if block.body.serialize(
    block.header.sketchSalt,
    len(packets)
  ) != bytes.fromhex(template["body"]):
    raise TestError("Failed to recreate the body.")

  block.mine(blsPrivKey, merit.blockchain.difficulty())
  merit.blockchain.add(block)

  rpc.call(
    "merit",
    "publishBlock",
    [
      template["id"],
      (
        template["header"] +
        block.header.proof.to_bytes(4, byteorder="little") +
        block.header.signature +
        block.body.serialize(block.header.sketchSalt, len(packets))
      ).hex()
    ]
  )

  verifyBlockchain(rpc, merit.blockchain)
Пример #29
0
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)

packets: List[VerificationPacket] = [
  VerificationPacket(first.hash, [0]),
  VerificationPacket(second.hash, [0]),
]

#Generate another 6 Blocks.
#Next block should have the packets.
block: Block = Block(
  BlockHeader(
    0,
    merit.blockchain.last(),
    BlockHeader.createContents(packets),
    1,
    bytes(4),
    BlockHeader.createSketchCheck(bytes(4), packets),
    0,
    merit.blockchain.blocks[-1].header.time + 1200
Пример #30
0
sendFilter: SpamFilter = SpamFilter(3)

edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
edPubKeys: List[ed25519.VerifyingKey] = [
    edPrivKey.get_verifying_key(),
    ed25519.SigningKey(b'\1' * 32).get_verifying_key()
]

#Create the Claim.
claim: Claim = Claim([(merit.mints[-1].hash, 0)], edPubKeys[0].to_bytes())
claim.amount = merit.mints[-1].outputs[0][1]
claim.sign(PrivateKey(0))
transactions.add(claim)
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   packets=[VerificationPacket(claim.hash,
                                               [0])]).finish(0, merit))

#Give the second key pair Merit.
merit.add(
    PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200,
                   minerID=PrivateKey(1)).finish(0, merit))

#Create two competing Sends.
packets: List[VerificationPacket] = []
for i in range(2):
    send: Send = Send(
        [(claim.hash, 0)],
        [(edPubKeys[i].to_bytes(),
          Claim.fromTransaction(transactions.txs[claim.hash]).amount)])
    send.sign(edPrivKey)
    send.beat(sendFilter)