예제 #1
0
 def __init__(self, genesis: bytes, blockTime: int, startDifficulty: int,
              lifetime: int) -> None:
     self.blockchain: Blockchain = Blockchain(genesis, blockTime,
                                              startDifficulty)
     self.state: State = State(lifetime)
     self.epochs = Epochs()
     self.mints: List[Mint] = []
예제 #2
0
def DepthOneTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Merit/Reorganizations/DepthOne.json", "r")
    chains: Dict[str, List[Dict[str, Any]]] = json.loads(file.read())
    file.close()

    #Load the alternate blockchain.
    alt: Blockchain = Blockchain.fromJSON(chains["alt"])

    #Send the alternate tip.
    def sendAlternateTip() -> None:
        header: bytes = rpc.meros.liveBlockHeader(alt.blocks[-1].header)
        req: bytes = rpc.meros.sync.recv()
        if req != (MessageType.BlockBodyRequest.toByte() + alt.blocks[-1].header.hash):
            raise TestError("Meros didn't request the BlockBody.")
        rpc.meros.blockBody(alt.blocks[-1])

        if rpc.meros.live.recv() != header:
            raise TestError("Meros didn't send back the BlockHeader.")

        #Verify the alternate Blockchain.
        verifyBlockchain(rpc, alt)

        #Raise SuccessError so the Liver doesn't fail when verifying the original chain.
        raise SuccessError("Meros re-organized to the alternate chain.")

    #Create and execute a Liver.
    Liver(
        rpc,
        chains["main"],
        callbacks={
            3: sendAlternateTip
        }
    ).live()
예제 #3
0
def VCompetingTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/Verification/Competing.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK", 60,
        int(
            "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            16), vectors["blockchain"])
    #Consensus.
    consensus: Consensus = Consensus.fromJSON(
        bytes.fromhex(
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        ),
        bytes.fromhex(
            "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
        ), vectors["consensus"])
    #Transactions.
    transactions: Transactions = Transactions.fromJSON(vectors["transactions"])

    #Create and execute a Liver/Syncer.
    Liver(rpc, blockchain, consensus, transactions).live()
    Syncer(rpc, blockchain, consensus, transactions).sync()
예제 #4
0
def LANPeersTest(rpc: RPC) -> None:
    #Blockchain. Solely used to get the genesis Block hash.
    blockchain: Blockchain = Blockchain()

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

    #Verify that sending a PeersRequest returns 0 peers.
    rpc.meros.peersRequest()
    if len(rpc.meros.sync.recv()) != 2:
        raise TestError("Meros sent peers.")

    #Create a new connection which identifies as a server.
    serverConnection: socket.socket = socket.socket(socket.AF_INET,
                                                    socket.SOCK_STREAM)
    serverConnection.connect(("127.0.0.1", rpc.meros.tcp))
    serverConnection.send(
        MessageType.Syncing.toByte() + (254).to_bytes(1, "big") +
        (254).to_bytes(1, "big") + (128).to_bytes(1, "big") +
        (6000).to_bytes(2, "big") + blockchain.blocks[0].header.hash, False)
    serverConnection.recv(38)
    sleep(1)

    #Verify Meros ignores us as a peer since we're only available over the local network.
    rpc.meros.peersRequest()
    res: bytes = rpc.meros.sync.recv()
    if len(res) != 2:
        raise TestError("Meros sent peers.")

    #Close the new connection.
    serverConnection.close()
예제 #5
0
def HundredTwentyFiveTest(rpc: RPC) -> None:
    #Meros allows connections from its own IP if they identify as 127.0.0.1.
    #We need to connect either through the LAN or through the public IP for this test to be valid.
    #The following code grabs the computer's 192 IP.
    lanIPFinder = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    lanIPFinder.connect(("meroscrypto.io", 443))
    lanIP = lanIPFinder.getsockname()[0]
    lanIPFinder.close()

    if not (lanIP.split(".")[0] in {"10", "172", "192"}):
        raise Exception("Failed to get the LAN IP.")

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

    #Connect to Meros.
    connection: socket.socket = socket.socket(socket.AF_INET,
                                              socket.SOCK_STREAM)
    connection.connect((lanIP, rpc.meros.tcp))
    try:
        connection.send(
            MessageType.Syncing.toByte() + (254).to_bytes(1, "big") +
            (254).to_bytes(1, "big") + (128).to_bytes(1, "big") +
            (6000).to_bytes(2, "big") + blockchain.blocks[0].header.hash,
            False)
        if len(connection.recv(38)) == 0:
            raise Exception("")
    except Exception:
        raise SuccessError(
            "Meros closed a connection from the same IP as itself which wasn't 127.0.0.1."
        )
    raise TestError(
        "Meros allowed a connection from the same IP as itself which wasn't 127.0.0.1."
    )
예제 #6
0
def DelayedMeritHolderTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Merit/Reorganizations/DelayedMeritHolder.json", "r")
    chains: Dict[str, List[Dict[str, Any]]] = json.loads(file.read())
    file.close()

    #Load the alternate blockchain.
    alt: Blockchain = Blockchain.fromJSON(chains["alt"])

    #Send the alternate tip.
    def sendAlternateTip() -> None:
        header: bytes = rpc.meros.liveBlockHeader(alt.blocks[-1].header)

        req: bytes = rpc.meros.sync.recv()
        if MessageType(req[0]) != MessageType.BlockListRequest:
            raise TestError("Meros didn't request the list of previous BlockHeaders.")
        if req[3 : 35] != alt.blocks[-1].header.hash:
            raise TestError("Meros didn't request the list of previous BlockHeaders for THIS header.")

        blockList: List[bytes] = []
        b: int = len(alt.blocks) - 2
        while b != -1:
            blockList.append(alt.blocks[b].header.hash)
            b -= 1
        rpc.meros.blockList(blockList)

        diff = -2
        while diff != -1:
            req = rpc.meros.sync.recv()
            if req != (MessageType.BlockHeaderRequest.toByte() + alt.blocks[diff].header.hash):
                raise TestError("Meros didn't request a previous BlockHeader.")
            rpc.meros.syncBlockHeader(alt.blocks[diff].header)
            diff += 1

        diff = -2
        while diff != 0:
            req = rpc.meros.sync.recv()
            if req != (MessageType.BlockBodyRequest.toByte() + alt.blocks[diff].header.hash):
                raise TestError("Meros didn't request a previous BlockBody.")
            rpc.meros.blockBody(alt.blocks[diff])
            diff += 1

        if rpc.meros.live.recv() != header:
            raise TestError("Meros didn't send back the BlockHeader.")

        #Verify the alternate Blockchain.
        verifyBlockchain(rpc, alt)

        #Raise SuccessError so the Liver doesn't fail when verifying the original chain.
        raise SuccessError("Meros re-organized to the alternate chain.")

    #Create and execute a Liver.
    Liver(
        rpc,
        chains["main"],
        callbacks={
            6: sendAlternateTip
        }
    ).live()
예제 #7
0
def DifficultyTest(rpc: RPC) -> None:
    #Blocks.
    file: IO[Any] = open("PythonTests/Vectors/Merit/BlankBlocks.json", "r")
    blocks: List[Dict[str, Any]] = json.loads(file.read())
    file.close()

    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(blocks)

    def checkDifficulty(block: int) -> None:
        if int(rpc.call("merit", "getDifficulty"),
               16) != blockchain.difficulties[block][0]:
            raise TestError("Difficulty doesn't match.")

    Liver(rpc, blocks, everyBlock=checkDifficulty).live()
예제 #8
0
    def fromJSON(json: List[Dict[str, Any]]) -> Any:
        result: Merit = Merit.__new__(Merit)

        result.blockchain = Blockchain.fromJSON(json)
        result.state = State()
        result.epochs = Epochs()
        result.mints = []

        for b in range(1, len(result.blockchain.blocks)):
            mint: Optional[Mint] = result.epochs.shift(result.state,
                                                       result.blockchain, b)
            if mint is not None:
                result.mints.append(mint)

            result.state.add(result.blockchain, b)
        return result
예제 #9
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.")
예제 #10
0
def ChainAdvancementTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Merit/BlankBlocks.json", "r")
    blocks: List[Dict[str, Any]] = json.loads(file.read())
    file.close()

    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK",
        60,
        int("FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 16),
        blocks
    )

    #Create and execute a Liver/Syncer.
    Liver(rpc, blockchain).live()
    Syncer(rpc, blockchain).sync()
예제 #11
0
    def fromJSON(genesis: bytes, blockTime: int, startDifficulty: int,
                 lifetime: int, transactions: Transactions,
                 consensus: Consensus, json: List[Dict[str, Any]]) -> Any:
        result: Merit = Merit(bytes(), 0, 0, 0)

        result.blockchain = Blockchain.fromJSON(genesis, blockTime,
                                                startDifficulty, json)
        result.state = State(lifetime)
        result.epochs = Epochs()

        for b in range(1, len(result.blockchain.blocks)):
            mints: List[Mint] = result.epochs.add(transactions, consensus,
                                                  result.state,
                                                  result.blockchain.blocks[b])
            result.mints += mints

            result.state.add(result.blockchain, result.blockchain.blocks[b])
        return result
예제 #12
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.")
예제 #13
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)
예제 #14
0
def StateTest(rpc: RPC) -> None:
    #Blocks.
    file: IO[Any] = open("PythonTests/Vectors/Merit/StateBlocks.json", "r")
    blocks: List[Dict[str, Any]] = json.loads(file.read())
    file.close()

    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(blocks)
    #State.
    state: State = State()

    def checkState(block: int) -> None:
        state.add(blockchain, block)

        for miner in state.unlocked:
            if rpc.call("merit", "getMerit", [miner]) != {
                    "unlocked": True,
                    "malicious": False,
                    "merit": state.unlocked[miner]
            }:
                raise TestError("Merit doesn't match.")

    Liver(rpc, blocks, everyBlock=checkState).live()
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.")
예제 #16
0
#JSON standard lib.
import json

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

#SpamFilter.
spamFilter: SpamFilter = SpamFilter(5)

#Blockchains.
packetedChain: Blockchain = Blockchain()
reorderedChain: Blockchain = Blockchain()

#Generate a Block granting the holder Merit.
block = Block(
    BlockHeader(0, packetedChain.last(), bytes(32), 1, bytes(4), bytes(32),
                blsPubKey.serialize(),
                packetedChain.blocks[-1].header.time + 1200), BlockBody())
#Mine it.
block.mine(blsPrivKey, packetedChain.difficulty())

#Add it.
packetedChain.add(block)
reorderedChain.add(block)
print("Generated Hundred Twenty Three Packet Block 1/2 " +
      str(len(packetedChain.blocks)) + ".")
예제 #17
0
from PythonTests.Classes.Merit.Block import Block
from PythonTests.Classes.Merit.Blockchain import Blockchain

#Blake2b standard function.
from hashlib import blake2b

#JSON standard lib.
import json

#Miner Private Key.
privKey: PrivateKey = PrivateKey(blake2b(b'\0', digest_size=32).digest())

#Blockchains.
bbFile: IO[Any] = open("PythonTests/Vectors/Merit/BlankBlocks.json", "r")
blocks: List[Dict[str, Any]] = json.loads(bbFile.read())
main: Blockchain = Blockchain.fromJSON(blocks)
#Only add the first 15 to the alt chain.
alt: Blockchain = Blockchain()
for b in range(15):
    alt.add(Block.fromJSON(blocks[b]))

#Generate an alternative fifteen Blocks.
for i in range(1, 15):
    #Create the next Block.
    block = Block(
        BlockHeader(
            0,
            alt.last(),
            bytes(32),
            1,
            bytes(4),
예제 #18
0
from PythonTests.Libs.BLS import PrivateKey

#Merit classes.
from PythonTests.Classes.Merit.BlockHeader import BlockHeader
from PythonTests.Classes.Merit.BlockBody import BlockBody
from PythonTests.Classes.Merit.Block import Block
from PythonTests.Classes.Merit.Blockchain import Blockchain

#Blake2b standard function.
from hashlib import blake2b

#JSON standard lib.
import json

#Blockchain.
blockchain: Blockchain = Blockchain()

#Miner Private Key.
privKey: PrivateKey = PrivateKey(blake2b(b'\0', digest_size=32).digest())

#Create the Block.
block: Block = Block(
    BlockHeader(0, blockchain.last(), bytes(32), 1, bytes(4), bytes(32),
                privKey.toPublicKey().serialize(),
                blockchain.blocks[-1].header.time + 1200), BlockBody())

#Generate blocks.
for i in range(1, 26):
    #Mine the Block.
    block.mine(privKey, blockchain.difficulty())
예제 #19
0
from PythonTests.Libs.BLS import PrivateKey

#Merit classes.
from PythonTests.Classes.Merit.BlockHeader import BlockHeader
from PythonTests.Classes.Merit.BlockBody import BlockBody
from PythonTests.Classes.Merit.Block import Block
from PythonTests.Classes.Merit.Blockchain import Blockchain

#Blake2b standard function.
from hashlib import blake2b

#JSON standard lib.
import json

#Blockchains.
main: Blockchain = Blockchain()
alt: Blockchain = Blockchain()

#Miner Private Keys.
privKeys: List[PrivateKey] = [
    PrivateKey(blake2b(b'\0', digest_size=32).digest()),
    PrivateKey(blake2b(b'\1', digest_size=32).digest())
]

#Create the Block to the first miner.
block: Block = Block(
    BlockHeader(0, main.last(), bytes(32), 1, bytes(4), bytes(32),
                privKeys[0].toPublicKey().serialize(),
                main.blocks[-1].header.time + 1200), BlockBody())
block.mine(privKeys[0], main.difficulty())
main.add(block)
예제 #20
0
#Ed25519 lib.
import ed25519

#Blake2b standard function.
from hashlib import blake2b

#JSON standard lib.
import json

cmFile: IO[Any] = open("PythonTests/Vectors/Transactions/ClaimedMint.json",
                       "r")
cmVectors: Dict[str, Any] = json.loads(cmFile.read())
#Transactions.
transactions: Transactions = Transactions.fromJSON(cmVectors["transactions"])
#Blockchain.
blockchain: Blockchain = Blockchain.fromJSON(cmVectors["blockchain"])
cmFile.close()

#SpamFilter.
sendFilter: SpamFilter = SpamFilter(3)

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

#Grab the Claim hash.
claim: bytes = blockchain.blocks[-1].body.packets[0].hash
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()
예제 #22
0
def HundredTwentyFourTest(
    rpc: RPC
) -> None:
    #Load the vectors.
    file: IO[Any] = open("PythonTests/Vectors/Merit/BlankBlocks.json", "r")
    vectors: List[Dict[str, Any]] = json.loads(file.read())
    file.close()

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

    #Parse the Blocks from the vectors.
    for i in range(2):
        blockchain.add(Block.fromJSON({}, vectors[i]))

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

    #Send another handshake with the latest block as the tip.
    rpc.meros.send(
        MessageType.Handshake.toByte() +
        (254).to_bytes(1, "big") +
        (254).to_bytes(1, "big") +
        b'\0' +
        blockchain.last(),
        False
    )

    #Verify Meros responds with their tail (the genesis).
    if rpc.meros.recv() != MessageType.BlockchainTail.toByte() + blockchain.blocks[0].header.hash:
        raise TestError("Meros didn't respond with its Blockchain's Tail.")

    #Handle sync requests.
    reqHash: bytes = bytes()
    bH: int = 0
    bB: int = 1
    while True:
        msg: bytes = rpc.meros.recv()

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

        elif MessageType(msg[0]) == MessageType.BlockListRequest:
            reqHash = msg[3 : 51]
            for b in range(len(blockchain.blocks)):
                if blockchain.blocks[b].header.hash == reqHash:
                    blockList: List[bytes] = []
                    for bl in range(1, msg[2] + 2):
                        if msg[1] == 0:
                            if b - bl < 0:
                                break
                            blockList.append(blockchain.blocks[b - bl].header.hash)

                        elif msg[1] == 1:
                            blockList.append(blockchain.blocks[b + bl].header.hash)

                        else:
                            raise TestError("Meros asked for an invalid direction in a BlockListRequest.")

                    if blockList == []:
                        rpc.meros.dataMissing()
                        break

                    rpc.meros.blockList(blockList)
                    break

                if b == len(blockchain.blocks):
                    rpc.meros.dataMissing()

        elif MessageType(msg[0]) == MessageType.BlockHeaderRequest:
            reqHash = msg[1 : 33]
            if reqHash != blockchain.blocks[2 - bH].header.hash:
                raise TestError("Meros asked for a Block Header that didn't belong to the next Block.")

            #Send the BlockHeader.
            rpc.meros.blockHeader(blockchain.blocks[2 - bH].header)
            bH += 1

        elif MessageType(msg[0]) == MessageType.BlockBodyRequest:
            reqHash = msg[1 : 33]
            if reqHash != blockchain.blocks[bB].header.hash:
                raise TestError("Meros asked for a Block Body that didn't belong to the next Block.")

            #Send the Block.
            rpc.meros.blockBody([], blockchain.blocks[bB])
            bB += 1

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

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

    #Verify the Blockchain.
    verifyBlockchain(rpc, blockchain)
예제 #23
0
def PartialTest(
    rpc: RPC
) -> None:
    file: IO[Any] = open("PythonTests/Vectors/Consensus/MeritRemoval/Partial.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK",
        60,
        int("FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 16),
        vectors["blockchain"]
    )

    #MeritRemoval.
    removal: PartiallySignedMeritRemoval = PartiallySignedMeritRemoval.fromJSON(vectors["removal"])
    #Consensus.
    consensus: Consensus = Consensus(
        bytes.fromhex("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
        bytes.fromhex("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC")
    )
    consensus.add(removal.e1)
    consensus.add(removal)

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

    #Create and execute a Liver to cause a Partial MeritRemoval.
    def sendElement() -> None:
        #Send the second Element.
        rpc.meros.signedElement(removal.se2)

        #Verify the MeritRemoval.
        if rpc.meros.recv() != (MessageType.SignedMeritRemoval.toByte() + removal.signedSerialize()):
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 2, 200, removal, True)

    Liver(
        rpc,
        blockchain,
        consensus,
        transactions,
        callbacks={
            2: sendElement,
            3: lambda: verifyMeritRemoval(rpc, 2, 200, removal, False)
        }
    ).live()

    #Create and execute a Liver to handle a Partial MeritRemoval.
    def sendMeritRemoval() -> None:
        #Send and verify the MeritRemoval.
        if rpc.meros.signedElement(removal) != rpc.meros.recv():
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 2, 200, removal, True)

    Liver(
        rpc,
        blockchain,
        consensus,
        transactions,
        callbacks={
            2: sendMeritRemoval,
            3: lambda: verifyMeritRemoval(rpc, 2, 200, removal, False)
        }
    ).live()

    #Create and execute a Syncer to handle a Partial MeritRemoval.
    Syncer(rpc, blockchain, consensus, transactions).sync()
    verifyMeritRemoval(rpc, 2, 200, removal, False)
예제 #24
0
def SameNonceTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/MeritRemoval/SameNonce.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK", 60,
        int(
            "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            16), vectors["blockchain"])

    #MeritRemoval.
    removal: SignedMeritRemoval = SignedMeritRemoval.fromJSON(
        vectors["removal"])
    #Consensus.
    consensus: Consensus = Consensus(
        bytes.fromhex(
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        ),
        bytes.fromhex(
            "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
        ))
    consensus.add(removal)

    #Data.
    data: Data = Data.fromJSON(vectors["data"])

    #Create and execute a Liver to cause a SameNonce MeritRemoval.
    def sendElements() -> None:
        #Send the Data/SignedVerifications.
        if rpc.meros.transaction(data) != rpc.meros.recv():
            raise TestError("Unexpected message sent.")

        if rpc.meros.signedElement(removal.se1) != rpc.meros.recv():
            raise TestError("Unexpected message sent.")
        rpc.meros.signedElement(removal.se2)

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

    Liver(rpc,
          blockchain,
          consensus,
          callbacks={
              1: sendElements,
              2: lambda: verifyMeritRemoval(rpc, 1, 100, removal, False)
          }).live()

    #Create and execute a Liver to handle a SameNonce MeritRemoval.
    def sendMeritRemoval() -> None:
        #Send and verify the MeritRemoval.
        if rpc.meros.signedElement(removal) != rpc.meros.recv():
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 1, 100, removal, True)

    Liver(rpc,
          blockchain,
          consensus,
          callbacks={
              1: sendMeritRemoval,
              2: lambda: verifyMeritRemoval(rpc, 1, 100, removal, False)
          }).live()

    #Create and execute a Syncer to handle a SameNonce MeritRemoval.
    Syncer(rpc, blockchain, consensus).sync()
    verifyMeritRemoval(rpc, 1, 100, removal, False)
예제 #25
0
def MultipleTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/MeritRemoval/Multiple.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK", 60,
        int(
            "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            16), vectors["blockchain"])

    #MeritRemovals.
    removal1: SignedMeritRemoval = SignedMeritRemoval.fromJSON(
        vectors["removal1"])
    removal2: SignedMeritRemoval = SignedMeritRemoval.fromJSON(
        vectors["removal2"])

    #Data.
    data: Data = Data.fromJSON(vectors["data"])

    #Create and execute a Liver to cause multiple MeritRemovals.
    def sendElements() -> None:
        #Send the Data.
        if rpc.meros.transaction(data) != rpc.meros.recv():
            raise TestError("Unexpected message sent.")

        #Send the first SignedElement.
        if rpc.meros.signedElement(removal1.se1) != rpc.meros.recv():
            raise TestError("Unexpected message sent.")
        #Send the second.
        rpc.meros.signedElement(removal1.se2)

        #Verify the first MeritRemoval.
        if rpc.meros.recv() != (MessageType.SignedMeritRemoval.toByte() +
                                removal1.signedSerialize()):
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 1, 100, removal1, True)

        #Send the third SignedElement.
        rpc.meros.signedElement(removal2.se2)

        #Meros should treat the first created MeritRemoval as the default MeritRemoval.
        if rpc.meros.recv() != (MessageType.SignedMeritRemoval.toByte() +
                                removal1.signedSerialize()):
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 1, 100, removal1, True)

    Liver(rpc,
          blockchain,
          callbacks={
              1: sendElements,
              2: lambda: verifyMeritRemoval(rpc, 1, 100, removal2, False)
          }).live()

    #Create and execute a Liver to handle multiple MeritRemovals.
    def sendMeritRemovals() -> None:
        #Send and verify the first MeritRemoval.
        msg = rpc.meros.signedElement(removal1)
        if msg != rpc.meros.recv():
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 1, 100, removal1, True)

        #Send the second MeritRemoval.
        rpc.meros.signedElement(removal2)
        #Meros should treat the first created MeritRemoval as the default.
        if msg != rpc.meros.recv():
            raise TestError("Meros didn't send us the Merit Removal.")
        verifyMeritRemoval(rpc, 1, 100, removal1, True)

    Liver(rpc,
          blockchain,
          callbacks={
              1: sendMeritRemovals,
              2: lambda: verifyMeritRemoval(rpc, 1, 100, removal2, False)
          }).live()
예제 #26
0
def ULimitTest(
    #pylint: disable=unused-argument
    rpc: RPC
) -> None:
    #Sleep 60 seconds so Meros can correct its FD count.
    sleep(60)

    #Create a Blockchain so we have the genesis Block hash.
    blockchain: Blockchain = Blockchain()

    #Create peers until Meros sends us busy.
    sockets: List[MerosSocket] = []
    while True:
        #Only create live sockets to trigger new peers for each socket.
        try:
            sockets.append(MerosSocket(5132, 254, 254, True, blockchain.blocks[0].header.hash))
        except BusyError as e:
            if e.handshake != (MessageType.Busy.toByte() + bytes(1)):
                raise TestError("Meros sent an invalid Busy message.")
            break

    #Trigger busy 32 more times to verify Meros doesn't still allocate file handles.
    for _ in range(32):
        try:
            MerosSocket(5132, 254, 254, True, blockchain.blocks[0].header.hash)
        except BusyError as e:
            if e.handshake != (MessageType.Busy.toByte() + bytes(1)):
                raise TestError("Meros sent an invalid Busy message.")
            continue
        raise TestError("Meros didn't send Busy despite being at capacity.")

    #Disconnect the last 50 sockets.
    for _ in range(50):
        sockets[-1].connection.shutdown(socket.SHUT_RDWR)
        sockets[-1].connection.close()
        del sockets[-1]

    #Send a Handshake over every remaining socket every 20 seconds for a minute.
    #Then Meros should update the amount of files it has open and accept 50 new sockets.
    for _ in range(3):
        for lSocket in sockets:
            lSocket.send(
                MessageType.Handshake.toByte() +
                (254).to_bytes(1, "big") +
                (254).to_bytes(1, "big") +
                b'\0\0\0' +
                blockchain.blocks[0].header.hash
            )
        sleep(20)

    #Connect 50 sockets and verify Meros doesn't think it's still at capacity.
    for _ in range(50):
        try:
            sockets.append(MerosSocket(5132, 254, 254, True, blockchain.blocks[0].header.hash))
        except BusyError:
            raise TestError("Meros thought it was at capcity when it wasn't.")

    #Verify connecting one more socket returns Busy.
    try:
        MerosSocket(5132, 254, 254, True, blockchain.blocks[0].header.hash)
    except BusyError:
        return
    raise TestError("Meros accepted a socket despite being at capcity.")
예제 #27
0
    def __init__(self) -> None:
        self.blockchain: Blockchain = Blockchain()
        self.state: State = State()
        self.epochs = Epochs()

        self.mints: List[Mint] = []
예제 #28
0
def PendingActionsTest(rpc: RPC) -> None:
    file: IO[Any] = open(
        "PythonTests/Vectors/Consensus/MeritRemoval/PendingActions.json", "r")
    vectors: Dict[str, Any] = json.loads(file.read())
    file.close()

    #Blockchain.
    blockchain: Blockchain = Blockchain.fromJSON(
        b"MEROS_DEVELOPER_NETWORK", 60,
        int(
            "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            16), vectors["blockchain"])

    #SignedVerifications.
    verifs: List[SignedVerification] = []
    for verif in vectors["verifications"]:
        verifs.append(SignedVerification.fromJSON(verif))
    #Removal.
    removal: SignedMeritRemoval = SignedMeritRemoval.fromJSON(
        vectors["removal"])

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

    #Send every Data/Verification.
    def sendDatasAndVerifications() -> None:
        #Send the Datas.
        for data in datas:
            if rpc.meros.transaction(data) != rpc.meros.recv():
                raise TestError("Unexpected message sent.")

        #Send the Verifications.
        for verif in verifs:
            if rpc.meros.signedElement(verif) != rpc.meros.recv():
                raise TestError("Unexpected message sent.")

        #Verify every Data has 100 Merit.
        for data in datas:
            if rpc.call("consensus", "getStatus",
                        [data.hash.hex()])["merit"] != 100:
                raise TestError(
                    "Meros didn't verify Transactions with received Verifications."
                )

    #Cause a MeritRemoval.
    def causeMeritRemoval() -> None:
        #Send every Data/;Verification.
        sendDatasAndVerifications()

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

        #Verify every Data has 0 Merit.
        for data in datas:
            if rpc.call("consensus", "getStatus",
                        [data.hash.hex()])["merit"] != 0:
                raise TestError(
                    "Meros didn't revert pending actions of a malicious MeritHolder."
                )

    #Send a MeritRemoval.
    def sendMeritRemoval() -> None:
        #Send every Data/;Verification.
        sendDatasAndVerifications()

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

        #Verify every Data has 0 Merit.
        for data in datas:
            if rpc.call("consensus", "getStatus",
                        [data.hash.hex()])["merit"] != 0:
                raise TestError(
                    "Meros didn't revert pending actions of a malicious MeritHolder."
                )

    #Check the Data's finalized with the proper amount of Merit and update the MeritRemoval.
    def check() -> None:
        #Verify the Datas have the Merit they should.
        for data in datas:
            if rpc.call("consensus", "getStatus",
                        [data.hash.hex()])["merit"] != 0:
                raise TestError(
                    "Meros didn't finalize with the reverted pending actions of a malicious MeritHolder."
                )

        #Update the MeritRemoval's nonce.
        removal.nonce = 6

        #Verify the MeritRemoval is now accessible with a nonce of 6.
        verifyMeritRemoval(rpc, 7, 0, removal, False)

    #Create and execute a Liver to cause a MeritRemoval.
    Liver(rpc, blockchain, callbacks={1: causeMeritRemoval, 7: check}).live()

    #Reset the MeritRemoval nonce.
    removal.nonce = 0

    #Create and execute a Liver to handle a MeritRemoval.
    Liver(rpc, blockchain, callbacks={1: sendMeritRemoval, 7: check}).live()
예제 #29
0
#Blockchain classes.
from PythonTests.Classes.Merit.BlockHeader import BlockHeader
from PythonTests.Classes.Merit.BlockBody import BlockBody
from PythonTests.Classes.Merit.Block import Block
from PythonTests.Classes.Merit.Blockchain import Blockchain

#Blake2b standard function.
from hashlib import blake2b

#JSON standard lib.
import json

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

#BLS Keys.
blsPrivKey: PrivateKey = PrivateKey(blake2b(b'\0', digest_size=32).digest())
blsPubKey: PublicKey = blsPrivKey.toPublicKey()

#Create a DataDifficulty.
dataDiffs: List[SignedDataDifficulty] = [
    SignedDataDifficulty(3, 0),
    SignedDataDifficulty(1, 1)
]
for dataDiff in dataDiffs:
    dataDiff.sign(0, blsPrivKey)

#Generate a Block containing the DataDifficulty.
예제 #30
0
파일: Multiple.py 프로젝트: ClashLuke/Meros
#JSON standard lib.
import json

#Consensus.
consensus: Consensus = Consensus(
    bytes.fromhex(
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    ),
    bytes.fromhex(
        "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
    ),
)
#Blockchain.
blockchain: Blockchain = Blockchain(
    b"MEROS_DEVELOPER_NETWORK", 60,
    int(
        "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
        16))

#BLS Keys.
privKey: blspy.PrivateKey = blspy.PrivateKey.from_seed(b'\0')
pubKey: blspy.PublicKey = privKey.get_public_key()

#Load a Multiple Block and load their MeritRemoval.
snFile: IO[Any] = open(
    "PythonTests/Vectors/Consensus/MeritRemoval/SameNonce.json", "r")
snVectors: Dict[str, Any] = json.loads(snFile.read())

blockchain.add(Block.fromJSON(snVectors["blockchain"][0]))

removal1: SignedMeritRemoval = SignedMeritRemoval.fromJSON(