def fromJSON( sendDiff: bytes, dataDiff: bytes, json: Dict[str, List[Dict[str, Any]]] ) -> Any: result = Consensus(sendDiff, dataDiff) for mh in json: for elem in json[mh]: if "signed" in elem: if elem["descendant"] == "Verification": result.add(SignedVerification.fromJSON(elem)) elif elem["descendant"] == "MeritRemoval": if elem["partial"]: result.add(PartiallySignedMeritRemoval.fromJSON(elem)) else: result.add(SignedMeritRemoval.fromJSON(elem)) else: raise Exception("JSON has an unsupported Element type: " + elem["descendant"]) else: if elem["descendant"] == "Verification": result.add(Verification.fromJSON(elem)) elif elem["descendant"] == "MeritRemoval": result.add(MeritRemoval.fromJSON(elem)) else: raise Exception("JSON has an unsupported Element type: " + elem["descendant"]) return result
def fromJSON(json: Dict[str, Any]) -> Any: se1: SignedElement = SignedElement() if json["elements"][0]["descendant"] == "Verification": se1 = SignedVerification.fromJSON(json["elements"][0]) else: raise Exception( "MeritRemoval constructed from an unsupported type of Element: " + json["elements"][0]["descendant"]) se2: SignedElement = SignedElement() if json["elements"][1]["descendant"] == "Verification": se2 = SignedVerification.fromJSON(json["elements"][1]) else: raise Exception( "MeritRemoval constructed from an unsupported type of Element: " + json["elements"][1]["descendant"]) result: SignedMeritRemoval = SignedMeritRemoval(se1, se2) result.nonce = json["nonce"] return result
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()
b"MEROS_DEVELOPER_NETWORK", 60, int( "FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 16)) #BLS Public Key. pubKey: blspy.PublicKey = blspy.PrivateKey.from_seed(b'\0').get_public_key() #Add a single Block to create Merit and load a MeritRemoval. snFile: IO[Any] = open( "PythonTests/Vectors/Consensus/MeritRemoval/SameNonce.json", "r") vectors: Dict[str, Any] = json.loads(snFile.read()) blockchain.add(Block.fromJSON(vectors["blockchain"][0])) consensus.add(SignedVerification.fromJSON(vectors["removal"]["elements"][0])) removal: PartiallySignedMeritRemoval = PartiallySignedMeritRemoval.fromJSON( vectors["removal"]) removal.nonce = 1 consensus.add(removal) snFile.close() #Generate a Block with a verif and a Block with the removal. for i in range(2): block: Block = Block( BlockHeader(i + 2, blockchain.last(), int(time()), consensus.getAggregate([(pubKey, i, i)])), BlockBody([(pubKey, i, consensus.getMerkle(pubKey, i, i))])) #Mine it.
def VParsableTest(rpc: RPC) -> None: file: IO[Any] = open( "PythonTests/Vectors/Consensus/Verification/Parsable.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( bytes.fromhex( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ), bytes.fromhex( "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" ), ) consensus.add(SignedVerification.fromJSON(vectors["verification"])) #Transactions. transactions: Transactions = Transactions() transactions.add(Data.fromJSON(vectors["data"])) #Handshake with the node. rpc.meros.connect(254, 254, 3) sentLast: bool = False reqHash: bytes = bytes() msg: bytes = bytes() height: int = 0 while True: try: msg = rpc.meros.recv() except TestError as e: if (not sentLast) or (str(e) != "Node disconnected us as a peer."): raise e break if MessageType(msg[0]) == MessageType.Syncing: rpc.meros.acknowledgeSyncing() elif MessageType(msg[0]) == MessageType.GetBlockHash: height = 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: holder: bytes = msg[1:49] rpc.meros.element(consensus.holders[holder][int.from_bytes( msg[49:53], "big")]) elif MessageType(msg[0]) == MessageType.TransactionRequest: sentLast = True rpc.meros.transaction(transactions.txs[msg[1:49]]) elif MessageType(msg[0]) == MessageType.SyncingOver: pass else: raise TestError("Unexpected message sent: " + msg.hex().upper())
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.")