예제 #1
0
def verifyTransaction(rpc: RPC, tx: Transaction) -> None:
    if rpc.call("transactions", "getTransaction",
                [tx.hash.hex()]) != tx.toJSON():
        raise TestError("Transaction doesn't match.")

    if rpc.call("consensus", "getStatus",
                [tx.hash.hex()])["verified"] != tx.verified:
        raise TestError("Transaction's status doesn't match.")
예제 #2
0
def verifyMeritRemoval(rpc: RPC, total: int, merit: int, holder: int,
                       pending: bool) -> None:
    #Verify the total Merit.
    if rpc.call("merit",
                "getTotalMerit") != total if pending else total - merit:
        raise TestError("Total Merit doesn't match.")

    #Verify the holder's Merit.
    if rpc.call("merit", "getMerit", [holder]) != {
            "unlocked": True,
            "malicious": pending,
            "merit": merit if pending else 0
    }:
        raise TestError("Holder's Merit doesn't match.")
예제 #3
0
파일: Verify.py 프로젝트: ClashLuke/Meros
def verifyBlockchain(
    rpc: RPC,
    blockchain: Blockchain
) -> None:
    #Verify the height.
    if rpc.call("merit", "getHeight") != len(blockchain.blocks):
        raise TestError("Height doesn't match.")

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

    #Verify the blocks.
    for block in blockchain.blocks:
        if rpc.call("merit", "getBlock", [block.header.nonce]) != block.toJSON():
            raise TestError("Block doesn't match.")
예제 #4
0
def verifyConsensus(rpc: RPC, consensus: Consensus) -> None:
    for pubKey in consensus.holders:
        for e in range(len(consensus.holders[pubKey])):
            if rpc.call(
                    "consensus", "getElement",
                [pubKey.hex(), e]) != consensus.holders[pubKey][e].toJSON():
                raise TestError("Element doesn't match.")
예제 #5
0
def verifyDataDifficulty(
    rpc: RPC,
    dataDiff: int
) -> None:
    sleep(1)

    if rpc.call("consensus", "getDataDifficulty") != dataDiff:
        raise TestError("Data Difficulty doesn't match.")
예제 #6
0
def verifySendDifficulty(
    rpc: RPC,
    sendDiff: int
) -> None:
    #Sleep to ensure data races aren't a problem.
    sleep(1)

    if rpc.call("consensus", "getSendDifficulty") != sendDiff:
        raise TestError("Send Difficulty doesn't match.")
예제 #7
0
def verifyBlockchain(rpc: RPC, blockchain: Blockchain) -> None:
    #Sleep to ensure data races aren't a problem.
    sleep(2)

    #Verify the height.
    if rpc.call("merit", "getHeight") != len(blockchain.blocks):
        raise TestError("Height doesn't match.")

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

    #Verify the Blocks.
    for b in range(len(blockchain.blocks)):
        if rpc.call("merit", "getBlock", [b]) != blockchain.blocks[b].toJSON():
            raise TestError("Block doesn't match.")

        if rpc.call("merit", "getBlock",
                    [blockchain.blocks[b].header.hash.hex().upper()
                     ]) != blockchain.blocks[b].toJSON():
            raise TestError("Block doesn't match.")
def HundredSixSignedElementsTest(rpc: RPC) -> None:
    #Blockchain. Solely used to get the genesis Block hash.
    blockchain: Blockchain = Blockchain()

    #BLS Key.
    blsPrivKey: PrivateKey = PrivateKey(
        blake2b(b'\0', digest_size=32).digest())
    sig: Signature = blsPrivKey.sign(bytes())

    #Create a Data.
    #This is required so the Verification isn't terminated early for having an unknown hash.
    data: bytes = bytes.fromhex(rpc.call("personal", "data", ["AA"]))

    #Create a signed Verification, SendDifficulty, and DataDifficulty.
    elements: List[SignedElement] = [
        SignedVerification(data, 1, sig),
        SignedSendDifficulty(bytes.fromhex("00" * 32), 0, 1, sig),
        SignedDataDifficulty(bytes.fromhex("00" * 32), 0, 1, sig)
    ]

    for elem in elements:
        #Handshake with the node.
        rpc.meros.connect(254, 254, blockchain.blocks[0].header.hash)

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

        #Sleep for a bit.
        sleep(0.2)

        #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.")
예제 #9
0
def verifyMeritRemoval(rpc: RPC, height: int, merit: int,
                       removal: MeritRemoval, pending: bool) -> None:
    #Verify the Merit Holder height.
    if rpc.call("consensus", "getHeight", [removal.holder.hex()]) != height:
        raise TestError("Merit Holder height doesn't match.")

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

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

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

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

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

    #Verify the Merit Holder's Merit.
    if rpc.call("merit", "getMerit", [removal.holder.hex()]) != {
            "live": True,
            "malicious": pending,
            "merit": merit if pending else 0
    }:
        raise TestError("Merit Holder's Merit doesn't match.")
예제 #10
0
def VUnknownTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Consensus/Verification/Parsable.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    #SignedVerification.
    sv: SignedVerification = SignedVerification.fromJSON(vectors["verification"])
    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK",
        60,
        int("FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 16),
        vectors["blockchain"]
    )
    file.close()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if rpc.call("merit", "getHeight") != 2:
        raise TestError("Meros added a Block with an unknown Verification.")
예제 #11
0
def EightyEightTest(rpc: RPC) -> None:
    #Ed25519 key.
    edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32)
    edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key()

    #BLS key.
    blsPrivKey: PrivateKey = PrivateKey(
        blake2b(b'\0', digest_size=32).digest())
    blsPubKey: str = blsPrivKey.toPublicKey().serialize().hex()

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

    #Merit.
    merit: Merit = Merit()
    #Spam Filter.
    dataFilter: SpamFilter = SpamFilter(bytes.fromhex("CC" * 32))

    #Handshake with the node.
    rpc.meros.connect(254, 254, merit.blockchain.blocks[0].header.hash)

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

    #Handle sync requests.
    reqHash: bytes = bytes()
    while True:
        msg: bytes = rpc.meros.recv()

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

        elif 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(merit.state.nicks, block)

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

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

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

    #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.transaction(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(
            merit.state.nicks, packets):
        raise TestError(
            "Block template doesn't have both Verification Packets.")

    #Mine the Block.
    block = Block(
        BlockHeader(
            0,
            block.header.hash,
            BlockHeader.createContents(merit.state.nicks, packets),
            1,
            template["header"][-43:-39],
            BlockHeader.createSketchCheck(template["header"][-43:-39],
                                          packets),
            0,
            int.from_bytes(template["header"][-4:], byteorder="big"),
        ),
        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(merit.state.nicks, 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)

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

    #Verify the Blockchain.
    verifyBlockchain(rpc, merit.blockchain)
예제 #12
0
def verifyTransaction(rpc: RPC, tx: Transaction) -> None:
    if rpc.call("transactions", "getTransaction",
                [tx.hash.hex()]) != tx.toJSON():
        raise TestError("Transaction doesn't match.")
예제 #13
0
def TElementTest(rpc: RPC) -> None:
    #BLS key.
    blsPrivKey: PrivateKey = PrivateKey(
        blake2b(b'\0', digest_size=32).digest())
    blsPubKey: str = blsPrivKey.toPublicKey().serialize().hex()

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

    #Merit.
    merit: Merit = Merit()

    #Handshake with the node.
    rpc.meros.connect(254, 254, merit.blockchain.blocks[0].header.hash)

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

    #Handle sync requests.
    reqHash: bytes = bytes()
    while True:
        msg: bytes = rpc.meros.recv()

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

        elif 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(merit.state.nicks, block)

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

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

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

    #Create and transmit a DataDifficulty.
    dataDiff: SignedDataDifficulty = SignedDataDifficulty(
        bytes.fromhex("00" * 32), 0, 0)
    dataDiff.sign(0, blsPrivKey)
    rpc.meros.signedElement(dataDiff)
    sleep(0.5)

    #Verify the block template has the DataDifficulty.
    template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate",
                                        [blsPubKey])
    template["header"] = bytes.fromhex(template["header"])
    if template["header"][36:68] != BlockHeader.createContents(
            merit.state.nicks, [], [dataDiff]):
        raise TestError("Block template doesn't have the Data Difficulty.")

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

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

    #Publish it.
    rpc.call("merit", "publishBlock", [
        template["id"],
        (template["header"] + block.header.proof.to_bytes(4, byteorder="big") +
         block.header.signature + block.body.serialize(
             merit.state.nicks, block.header.sketchSalt)).hex()
    ])

    #Create and transmit a new DataDifficulty.
    dataDiff = SignedDataDifficulty(bytes.fromhex("AA" * 32), 1, 0)
    dataDiff.sign(0, blsPrivKey)
    rpc.meros.signedElement(dataDiff)
    sleep(0.5)

    #Verify the block template has the DataDifficulty.
    template = rpc.call("merit", "getBlockTemplate", [blsPubKey])
    template["header"] = bytes.fromhex(template["header"])
    if template["header"][36:68] != BlockHeader.createContents(
            merit.state.nicks, [], [dataDiff]):
        raise TestError("Block template doesn't have the new Data Difficulty.")

    #Create and transmit a new DataDifficulty reusing an existing nonce.
    signatures: List[Signature] = [dataDiff.signature]
    dataDiff = SignedDataDifficulty(bytes.fromhex("BB" * 32), 1, 0)
    dataDiff.sign(0, blsPrivKey)
    signatures.append(dataDiff.signature)
    rpc.meros.signedElement(dataDiff)
    sleep(0.5)

    #Verify the block template has a MeritRemoval.
    mr: MeritRemoval = MeritRemoval(
        SignedDataDifficulty(bytes.fromhex("AA" * 32), 1, 0),
        SignedDataDifficulty(bytes.fromhex("BB" * 32), 1, 0), False)
    template = rpc.call("merit", "getBlockTemplate", [blsPubKey])
    template["header"] = bytes.fromhex(template["header"])
    if template["header"][36:68] != BlockHeader.createContents(
            merit.state.nicks, [], [mr]):
        raise TestError("Block template doesn't have the Merit Removal.")

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

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

    #Publish it.
    rpc.call("merit", "publishBlock", [
        template["id"],
        (template["header"] + block.header.proof.to_bytes(4, byteorder="big") +
         block.header.signature + block.body.serialize(
             merit.state.nicks, block.header.sketchSalt)).hex()
    ])

    #Verify the Blockchain.
    verifyBlockchain(rpc, merit.blockchain)
def HundredSixBlockElementsTest(rpc: RPC) -> None:
    #Load the vectors.
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/HundredSix/BlockElements.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain. Solely used to get the genesis Block hash.
    blockchain: Blockchain = Blockchain()

    #Transactions.
    transactions: Transactions = Transactions.fromJSON(vectors["transactions"])

    #Parse the Blocks from the vectors.
    blocks: List[Block] = []
    for block in vectors["blocks"]:
        blocks.append(Block.fromJSON({}, block))

    for block in blocks:
        #Handshake with the node.
        rpc.meros.connect(254, 254, blockchain.blocks[0].header.hash)

        #Send the Block.
        rpc.meros.blockHeader(block.header)

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

        #Handle sync requests.
        reqHash: bytes = bytes()
        while True:
            try:
                msg: bytes = rpc.meros.recv()
            except TestError:
                if not blockBodySynced:
                    raise TestError(
                        "Node disconnected us before syncing the body.")

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

                #Since the node didn't crash, break out of this loop to trigger the next test case.
                break

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

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

            elif MessageType(msg[0]) == MessageType.SketchHashesRequest:
                if not block.body.packets:
                    raise TestError(
                        "Meros asked for Sketch Hashes from a Block without any."
                    )

                reqHash = msg[1:33]
                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))

                #Send the Sketch Hashes.
                rpc.meros.sketchHashes(hashes)

            elif MessageType(msg[0]) == MessageType.SketchHashRequests:
                if not block.body.packets:
                    raise TestError(
                        "Meros asked for Verification Packets from a Block without any."
                    )

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

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

                if reqHash not in transactions.txs:
                    raise TestError(
                        "Meros asked for a non-existent Transaction.")

                rpc.meros.transaction(transactions.txs[reqHash])

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

            elif MessageType(msg[0]) == MessageType.BlockHeader:
                #Raise a TestError if the Block was added.
                raise TestError("Meros synced a Block with an invalid holder.")

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

        #Reset the node.
        rpc.reset()
예제 #15
0
def HundredFiftyFiveTest(rpc: RPC) -> None:
    #Ed25519 keys.
    edPrivKeys: List[ed25519.SigningKey] = [
        ed25519.SigningKey(b'\0' * 32),
        ed25519.SigningKey(b'\1' * 32)
    ]
    edPubKeys: List[ed25519.VerifyingKey] = [
        edPrivKeys[0].get_verifying_key(), edPrivKeys[1].get_verifying_key()
    ]

    #BLS keys.
    blsPrivKey: PrivateKey = PrivateKey(
        bytes.fromhex(rpc.call("personal", "getMiner")))
    blsPubKey: bytes = blsPrivKey.toPublicKey().serialize()

    #Blockchain.
    blockchain: Blockchain = Blockchain()
    #Spam Filter.
    dataFilter: SpamFilter = SpamFilter(5)

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

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

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

    #Handle the fact Meros will now broadcast it to us.
    if MessageType(rpc.meros.live.recv()[0]) != MessageType.BlockHeader:
        raise TestError("Meros didn't broadcast the Block it just published.")

    #Create the Datas.
    datas: List[Data] = [
        Data(bytes(32), edPubKeys[0].to_bytes()),
        Data(bytes(32), edPubKeys[1].to_bytes())
    ]

    for d in range(len(datas)):
        #Sign, and mine the Data.
        datas[d].sign(edPrivKeys[d])
        datas[d].beat(dataFilter)

        #Send the Data and verify Meros sends it back.
        if rpc.meros.liveTransaction(datas[d]) != rpc.meros.live.recv():
            raise TestError("Meros didn't send back the Data.")

        #Verify Meros sends back a Verification.
        res: bytes = rpc.meros.live.recv()
        if MessageType(res[0]) != MessageType.SignedVerification:
            raise TestError("Meros didn't send a SignedVerification.")

        verif: SignedVerification = SignedVerification(datas[d].hash)
        verif.sign(0, blsPrivKey)
        if res[1:] != verif.signedSerialize():
            raise TestError(
                "Meros didn't send the correct SignedVerification.")
예제 #16
0
def verifySendDifficulty(rpc: RPC, sendDiff: bytes) -> None:
    if rpc.call("consensus", "getSendDifficulty") != sendDiff.hex().upper():
        raise TestError("Send Difficulty doesn't match.")
예제 #17
0
def verifyDataDifficulty(rpc: RPC, dataDiff: bytes) -> None:
    if rpc.call("consensus", "getDataDifficulty") != dataDiff.hex().upper():
        raise TestError("Data Difficulty doesn't match.")