def SameNonceTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/Vectors/Consensus/MeritRemoval/SameNonce.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) file.close() #MeritRemoval. #pylint: disable=no-member removal: SignedMeritRemoval = SignedMeritRemoval.fromSignedJSON( vectors["removal"]) #Create and execute a Liver to cause a Signed MeritRemoval. def sendElements() -> None: #Send the Elements. rpc.meros.signedElement(removal.se1) rpc.meros.signedElement(removal.se2) #Verify the first Element. if rpc.meros.live.recv() != (MessageType.SignedDataDifficulty.toByte() + removal.se1.signedSerialize()): raise TestError("Meros didn't send us the first Data Difficulty.") #Verify the MeritRemoval. if rpc.meros.live.recv() != (MessageType.SignedMeritRemoval.toByte() + removal.signedSerialize()): raise TestError("Meros didn't send us the Merit Removal.") verifyMeritRemoval(rpc, 1, 1, removal.holder, True) Liver(rpc, vectors["blockchain"], callbacks={ 1: sendElements, 2: lambda: verifyMeritRemoval(rpc, 1, 1, removal.holder, False) }).live() #Create and execute a Liver to handle a Signed MeritRemoval. def sendMeritRemoval() -> None: #Send and verify the MeritRemoval. if rpc.meros.signedElement(removal) != rpc.meros.live.recv(): raise TestError("Meros didn't send us the Merit Removal.") verifyMeritRemoval(rpc, 1, 1, removal.holder, True) Liver(rpc, vectors["blockchain"], callbacks={ 1: sendMeritRemoval, 2: lambda: verifyMeritRemoval(rpc, 1, 1, removal.holder, False) }).live() #Create and execute a Syncer to handle a Signed MeritRemoval. Syncer(rpc, vectors["blockchain"]).sync() verifyMeritRemoval(rpc, 1, 1, removal.holder, False)
def PartialTest( rpc: RPC ) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Consensus/MeritRemoval/Partial.json", "r") as file: vectors = json.loads(file.read()) removal: PartialMeritRemoval = PartialMeritRemoval.fromSignedJSON(vectors["removal"]) #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.live.recv() != ( MessageType.SignedMeritRemoval.toByte() + removal.serialize() ): raise TestError("Meros didn't send us the Merit Removal.") verifyMeritRemoval(rpc, 2, 2, removal.holder, True) Liver( rpc, vectors["blockchain"], callbacks={ 2: sendElement, 3: lambda: verifyMeritRemoval(rpc, 2, 2, removal.holder, False) } ).live() #Create and execute a Liver to handle a Partial MeritRemoval. def sendMeritRemoval() -> None: #Send and verify the MeritRemoval. if rpc.meros.meritRemoval(removal) != rpc.meros.live.recv(): raise TestError("Meros didn't send us the Merit Removal.") verifyMeritRemoval(rpc, 2, 2, removal.holder, True) Liver( rpc, vectors["blockchain"], callbacks={ 2: sendMeritRemoval, 3: lambda: verifyMeritRemoval(rpc, 2, 2, removal.holder, False) } ).live() #Create and execute a Syncer to handle a Partial MeritRemoval. Syncer(rpc, vectors["blockchain"]).sync() verifyMeritRemoval(rpc, 2, 2, removal.holder, False)
def VCompetingTest(rpc: RPC) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Consensus/Verification/Competing.json", "r") as file: vectors = json.loads(file.read()) transactions: Transactions = Transactions.fromJSON(vectors["transactions"]) #Function to verify the right Transaction was confirmed. def verifyConfirmation() -> None: if not rpc.call("consensus", "getStatus", {"hash": vectors["verified"]})["verified"]: raise TestError( "Didn't verify the Send which should have been verified.") if rpc.call("consensus", "getStatus", {"hash": vectors["beaten"]})["verified"]: raise TestError( "Did verify the Send which should have been beaten.") Liver(rpc, vectors["blockchain"], transactions, callbacks={ 19: verifyConfirmation }).live() Syncer(rpc, vectors["blockchain"], transactions).sync()
def UnionedFamiliesMultipleWinnersTest(rpc: RPC) -> None: vectors: Dict[str, Any] with open( "e2e/Vectors/Consensus/Families/UnionedFamiliesMultipleWinners.json", "r") as file: vectors = json.loads(file.read()) sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]] def sendSends() -> None: for s in range(len(sends)): if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast a Send.") def verifyMultipleWon() -> None: for send in [sends[1], *sends[3:]]: if rpc.call("consensus", "getStatus", [send.hash.hex()])["verified"]: raise TestError( "Meros verified a transaction which was beaten by another transaction." ) for send in [sends[0], sends[2]]: if not rpc.call("consensus", "getStatus", [send.hash.hex()])["verified"]: raise TestError( "Meros didn't verify the verified transaction for each original family." ) Liver(rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"]), callbacks={ 44: sendSends, 50: verifyMultipleWon }).live()
def RespondsWithRequestedCapacityTest( rpc: RPC ) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Merit/TwoHundredSeventyFour/RespondsWithRequestedCapacity.json", "r") as file: vectors = json.loads(file.read()) def requestWithCapacity() -> None: block: Block = Block.fromJSON(vectors["blockchain"][-1]) #Request 3/6 Transactions. rpc.meros.sync.send(MessageType.BlockBodyRequest.toByte() + block.header.hash + (3).to_bytes(4, "little")) if rpc.meros.sync.recv() != (MessageType.BlockBody.toByte() + block.body.serialize(block.header.sketchSalt, 3)): raise TestError("Meros didn't respond with the requested capacity.") #Request 8/6 Transactions. rpc.meros.sync.send(MessageType.BlockBodyRequest.toByte() + block.header.hash + (8).to_bytes(4, "little")) if rpc.meros.sync.recv() != (MessageType.BlockBody.toByte() + block.body.serialize(block.header.sketchSalt, 6)): raise TestError("Meros didn't respond with the requested capacity (normalized).") Liver( rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"]), callbacks={ 2: requestWithCapacity } ).live()
def testBlockchain( b: int ) -> None: #Data. data: Data = Data.fromJSON(vectors["data"]) #pylint: disable=no-member #MeritRemoval. removal: SignedMeritRemoval = SignedMeritRemoval.fromSignedJSON(vectors["removals"][b]) #Create and execute a Liver to send the MeritRemoval. def sendMeritRemoval() -> None: #Send the Data. if rpc.meros.liveTransaction(data) != rpc.meros.live.recv(): raise TestError("Meros didn't send back the Data.") rpc.meros.signedElement(removal) try: if len(rpc.meros.live.recv()) != 0: raise Exception() except TestError: raise SuccessError("Meros rejected our MeritRemoval created from the same Element.") except Exception: raise TestError("Meros accepted our MeritRemoval created from the same Element.") Liver( rpc, vectors["blockchain"], callbacks={ 1: sendMeritRemoval } ).live()
def NodeThresholdTest(rpc: RPC) -> None: edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32) dataFilter: SpamFilter = SpamFilter(5) datas: List[Data] = [Data(bytes(32), edPrivKey.get_verifying_key())] datas[-1].sign(edPrivKey) datas[-1].beat(dataFilter) def verifyThreshold(b: int) -> None: rpc.meros.liveTransaction(datas[-1]) datas.append(Data(datas[-1].hash, b"a")) datas[-1].sign(edPrivKey) datas[-1].beat(dataFilter) #Swallow the new Data(s). if b == 1: rpc.meros.live.recv() rpc.meros.live.recv() #Check the threshold. threshold: int = rpc.call("consensus", "getStatus", {"hash": datas[-2].hash.hex()})["threshold"] if b < 9: if threshold != ((max(b + 6, 5) // 5 * 4) + 1): raise TestError( "Meros didn't calculate the right node threshold. That said, this isn't defined by the protocol." ) elif threshold != 5: raise TestError("Meros didn't lower the node threshold.") with open("e2e/Vectors/Merit/BlankBlocks.json", "r") as file: Liver(rpc, json.loads(file.read())[:9], everyBlock=verifyThreshold).live()
def DataDifficultyTest(rpc: RPC) -> None: file: IO[Any] = open( "e2e/Vectors/Consensus/Difficulties/DataDifficulty.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) file.close() #Verify functions. vddStarting: Callable[[], None] = lambda: verifyDataDifficulty(rpc, 5) vddEarnedVote: Callable[[], None] = lambda: verifyDataDifficulty(rpc, 2) vddVoted: Callable[[], None] = lambda: verifyDataDifficulty(rpc, 1) def vmr() -> None: verifyMeritRemoval(rpc, 52, 52, 0, False) vddStarting() def vEarnedBack() -> None: vddStarting() #Create and execute a Liver/Syncer. Liver(rpc, vectors["blockchain"], callbacks={ 26: vddStarting, 50: vddEarnedVote, 51: vddVoted, 52: vmr, 103: vEarnedBack }).live() Syncer(rpc, vectors["blockchain"]).sync()
def FiftyTest(rpc: RPC) -> None: with open("e2e/Vectors/Transactions/Fifty.json", "r") as file: vectors: Dict[str, Any] = json.loads(file.read()) Liver(rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"])).live() Syncer(rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"])).sync()
def LowerHashTieBreakTest(rpc: RPC) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Consensus/Families/LowerHashTieBreak.json", "r") as file: vectors = json.loads(file.read()) datas: List[Data] = [Data.fromJSON(data) for data in vectors["datas"]] def sendDatas() -> None: for d in range(len(datas)): if rpc.meros.liveTransaction(datas[d]) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast a Data.") def verifyLowerHashWon() -> None: data: Data = datas[1] if int.from_bytes(data.hash, "little") > int.from_bytes( datas[2].hash, "little"): data = datas[2] if not rpc.call("consensus", "getStatus", {"hash": data.hash.hex()})["verified"]: raise TestError( "Meros didn't verify the tied Transaction with a lower hash.") Liver(rpc, vectors["blockchain"], callbacks={ 40: sendDatas, 46: verifyLowerHashWon }).live()
def UnionedFamiliesSingleWinnerTest( rpc: RPC ) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Consensus/Families/UnionedFamiliesSingleWinner.json", "r") as file: vectors = json.loads(file.read()) sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]] def sendSends() -> None: for s in range(len(sends)): if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast a Send.") def verifyUnionizingWon() -> None: for send in sends[:-1]: if rpc.call("consensus", "getStatus", {"hash": send.hash.hex()})["verified"]: raise TestError("Meros verified a transaction which was beaten by a unionizing transaction.") if not rpc.call("consensus", "getStatus", {"hash": sends[-1].hash.hex()})["verified"]: raise TestError("Meros didn't verify the verified unionizing transaction.") Liver( rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"]), callbacks={ 45: sendSends, 51: verifyUnionizingWon } ).live()
def ChainAdvancementTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/Vectors/Merit/BlankBlocks.json", "r") chain: List[Dict[str, Any]] = json.loads(file.read()) file.close() Liver(rpc, chain).live() Syncer(rpc, chain).sync()
def HundredSeventyFiveTest( rpc: RPC ) -> None: file: IO[Any] = open("e2e/Vectors/Merit/HundredSeventyFive.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) file.close() transactions: Transactions = Transactions.fromJSON(vectors["transactions"]) verif: SignedVerification = SignedVerification.fromSignedJSON(vectors["verification"]) def sendDatasAndVerif() -> None: for tx in transactions.txs: if rpc.meros.liveTransaction(transactions.txs[tx]) != rpc.meros.live.recv(): raise TestError("Meros didn't send us back the Data.") if rpc.meros.signedElement(verif) != rpc.meros.live.recv(): raise TestError("Meros didn't send us back the Verification.") Liver( rpc, vectors["blockchain"], transactions, callbacks={ 1: sendDatasAndVerif } ).live([verif.hash])
def StateTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/Vectors/Merit/State.json", "r") blocks: List[Dict[str, Any]] = json.loads(file.read()) file.close() blockchain: Blockchain = Blockchain.fromJSON(blocks) state: State = State() def checkState(block: int) -> None: state.add(blockchain, block) meritSum: int = 0 for miner in range(len(state.balances)): meritSum += state.balances[miner] if rpc.call("merit", "getMerit", [miner]) != { "status": "Unlocked", "malicious": False, "merit": state.balances[miner] }: raise TestError("Merit doesn't match.") if meritSum != min(block, state.lifetime): raise TestError("Merit sum is invalid.") Liver(rpc, blocks, everyBlock=checkState).live()
def PendingDieRegainTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/Vectors/Merit/LockedMerit/PendingDieRegain.json", "r") chain: List[Dict[str, Any]] = json.loads(file.read()) file.close() def verifyCorrectlyLocked(height: int) -> None: merit: Dict[str, Any] = rpc.call("merit", "getMerit", [0]) merit = {"merit": merit["merit"], "status": merit["status"]} if height < 9: if merit != {"merit": 1, "status": "Unlocked"}: raise TestError("Merit was locked early.") elif height < 100: if merit != {"merit": 1, "status": "Locked"}: raise TestError("Merit wasn't locked.") elif height == 100: if merit != {"merit": 1, "status": "Pending"}: raise TestError("Merit wasn't pending.") elif height == 101: if merit != {"merit": 0, "status": "Unlocked"}: raise TestError("Merit didn't die and become unlocked.") elif height == 102: #pylint: disable=global-statement global correctVectorsHeight correctVectorsHeight = True if merit != {"merit": 1, "status": "Unlocked"}: raise TestError("Didn't regain Merit which was unlocked.") Liver(rpc, chain, everyBlock=verifyCorrectlyLocked).live() if not correctVectorsHeight: raise Exception("PendingDieRegain vectors have an invalid length.")
def LockedMeritDifficultyTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/Vectors/Consensus/Difficulties/LockedMerit.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) file.close() def verifyVotedAndUnlocked() -> None: if rpc.call("merit", "getMerit", [0])["status"] != "Unlocked": raise Exception(INVALID_TEST) verifySendDifficulty(rpc, 2) verifyDataDifficulty(rpc, 2) def verifyDiscountedAndLocked() -> None: if rpc.call("merit", "getMerit", [0])["status"] != "Locked": raise Exception(INVALID_TEST) verifySendDifficulty(rpc, 3) verifyDataDifficulty(rpc, 5) def verifyCountedAndPending() -> None: if rpc.call("merit", "getMerit", [0])["status"] != "Pending": raise Exception(INVALID_TEST) verifySendDifficulty(rpc, 2) verifyDataDifficulty(rpc, 2) Liver(rpc, vectors["blockchain"], callbacks={ 50: verifyVotedAndUnlocked, 59: verifyDiscountedAndLocked, 60: verifyCountedAndPending }).live()
def TwoHundredThirtyEightTest( rpc: RPC ) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Transactions/Prune/TwoHundredThirtyEight.json", "r") as file: vectors = json.loads(file.read()) datas: List[Data] = [Data.fromJSON(data) for data in vectors["datas"]] verif: SignedVerification = SignedVerification.fromSignedJSON(vectors["verification"]) def sendDatas() -> None: for d in range(len(datas)): if rpc.meros.liveTransaction(datas[d]) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast a Data.") if rpc.meros.signedElement(verif) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast the Verification.") Liver( rpc, vectors["blockchain"], callbacks={ 42: sendDatas } ).live()
def DescendantHighestUnverifiedParentTest(rpc: RPC) -> None: vectors: Dict[str, Any] with open( "e2e/Vectors/Consensus/Families/DescendantHighestUnverifiedParent.json", "r") as file: vectors = json.loads(file.read()) sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]] def sendSends() -> None: for s in range(len(sends)): if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast a Send.") def verifyDescendantLost() -> None: for send in sends[1:]: if rpc.call("consensus", "getStatus", {"hash": send.hash.hex()})["verified"]: raise TestError( "Meros verified a beaten transaction or one of its children (one of which is impossible)." ) if not rpc.call("consensus", "getStatus", {"hash": sends[0].hash.hex()})["verified"]: raise TestError( "Meros either didn't verify the descendant or its parent.") Liver(rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"]), callbacks={ 45: sendSends, 51: verifyDescendantLost }).live()
def HTTSwapTest( rpc: RPC ) -> None: file: IO[Any] = open("e2e/Vectors/Consensus/MeritRemoval/HundredTwentyThree/Swap.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) file.close() def sendRepeatMeritRemoval() -> None: #Send the Block containing the modified Merit Removal. block: Block = Block.fromJSON(vectors["blockchain"][-1]) rpc.meros.liveBlockHeader(block.header) #Flag of if the Block's Body synced. blockBodySynced: bool = False #Handle sync requests. reqHash: bytes = bytes() while True: if blockBodySynced: #Sleep for a second so Meros handles the Block. sleep(1) #Try receiving from the Live socket, where Meros sends keep-alives. try: if len(rpc.meros.live.recv()) != 0: raise Exception() except TestError: #Verify the height is 3. #The genesis Block, the Block granting Merit, and the Block containing the MeritRemoval originally. try: if rpc.call("merit", "getHeight") != 3: raise Exception() except Exception: raise TestError("Node added a Block containg a repeat MeritRemoval.") #Since the node didn't add the Block, raise SuccessError. raise SuccessError("Node didn't add a Block containing a repeat MeritRemoval.") except Exception: raise TestError("Meros sent a keep-alive.") msg: bytes = rpc.meros.sync.recv() if MessageType(msg[0]) == MessageType.BlockBodyRequest: reqHash = msg[1 : 33] if reqHash != block.header.hash: raise TestError("Meros asked for a Block Body that didn't belong to the Block we just sent it.") #Send the BlockBody. blockBodySynced = True rpc.meros.blockBody(block) else: raise TestError("Unexpected message sent: " + msg.hex().upper()) Liver( rpc, vectors["blockchain"], callbacks={ 2: sendRepeatMeritRemoval } ).live()
def LockedMeritDifficultyTest(rpc: RPC) -> None: def verifyVotedAndUnlocked() -> None: if rpc.call("merit", "getMerit", {"nick": 0})["status"] != "Unlocked": raise Exception(INVALID_TEST) verifySendDifficulty(rpc, 2) verifyDataDifficulty(rpc, 2) def verifyDiscountedAndLocked() -> None: if rpc.call("merit", "getMerit", {"nick": 0})["status"] != "Locked": raise Exception(INVALID_TEST) verifySendDifficulty(rpc, 3) verifyDataDifficulty(rpc, 5) def verifyCountedAndPending() -> None: if rpc.call("merit", "getMerit", {"nick": 0})["status"] != "Pending": raise Exception(INVALID_TEST) verifySendDifficulty(rpc, 2) verifyDataDifficulty(rpc, 2) with open("e2e/Vectors/Consensus/Difficulties/LockedMerit.json", "r") as vectors: Liver(rpc, json.loads(vectors.read()), callbacks={ 50: verifyVotedAndUnlocked, 59: verifyDiscountedAndLocked, 60: verifyCountedAndPending }).live()
def DepthOneTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/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.") with raises(SuccessError): Liver(rpc, chains["main"], callbacks={3: sendAlternateTip}).live()
def UnmentionedBeatMentionedTest( rpc: RPC ) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Consensus/Families/UnmentionedBeatMentioned.json", "r") as file: vectors = json.loads(file.read()) datas: List[Data] = [Data.fromJSON(data) for data in vectors["datas"]] verif: SignedVerification = SignedVerification.fromSignedJSON(vectors["verification"]) def sendDatas() -> None: for d in range(len(datas)): if rpc.meros.liveTransaction(datas[d]) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast a Data.") #Might as well send this now. if rpc.meros.signedElement(verif) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast the Verification.") def verifyMentionedWon() -> None: if not rpc.call("consensus", "getStatus", [datas[2].hash.hex()])["verified"]: raise TestError("Meros didn't verify the only Transaction on chain which has finalized.") Liver( rpc, vectors["blockchain"], callbacks={ 41: sendDatas, 47: verifyMentionedWon } ).live()
def GetDifficultyTest( rpc: RPC ) -> None: #Check the global difficulty. if rpc.call("consensus", "getSendDifficulty", auth=False) != 3: raise TestError("getSendDifficulty didn't reply properly.") if rpc.call("consensus", "getDataDifficulty", auth=False) != 5: raise TestError("getDataDifficulty didn't reply properly.") #Check the difficulties for a holder who doesn't exist. try: rpc.call("consensus", "getSendDifficulty", {"holder": 0}, False) raise TestError("") except TestError as e: if str(e) != "-2 Holder doesn't have a SendDifficulty.": raise TestError("getSendDifficulty didn't raise when asked about a non-existent holder.") try: rpc.call("consensus", "getDataDifficulty", {"holder": 0}, False) raise TestError("") except TestError as e: if str(e) != "-2 Holder doesn't have a DataDifficulty.": raise TestError("getDataDifficulty didn't raise when asked about a non-existent holder.") def voteAndVerify() -> None: #Check the difficulties for a holder who has yet to vote. try: rpc.call("consensus", "getSendDifficulty", {"holder": 0}, False) raise TestError("") except TestError as e: if str(e) != "-2 Holder doesn't have a SendDifficulty.": raise TestError("getSendDifficulty didn't raise when asked about a holder who has yet to vote.") try: rpc.call("consensus", "getDataDifficulty", {"holder": 0}, False) raise TestError("") except TestError as e: if str(e) != "-2 Holder doesn't have a DataDifficulty.": raise TestError("getDataDifficulty didn't raise when asked about a holder who has yet to vote.") #Create the votes. sendDiff: SignedSendDifficulty = SignedSendDifficulty(6, 0) sendDiff.sign(0, PrivateKey(0)) dataDiff: SignedDataDifficulty = SignedDataDifficulty(10, 1) dataDiff.sign(0, PrivateKey(0)) #Send them. rpc.meros.signedElement(sendDiff) rpc.meros.signedElement(dataDiff) rpc.meros.live.recv() rpc.meros.live.recv() #Check them. if rpc.call("consensus", "getSendDifficulty", {"holder": 0}, False) != 6: raise TestError("getSendDifficulty didn't reply with the holder's current difficulty.") if rpc.call("consensus", "getDataDifficulty", {"holder": 0}, False) != 10: raise TestError("getDataDifficulty didn't reply with the holder's current difficulty.") with open("e2e/Vectors/Merit/BlankBlocks.json", "r") as file: Liver(rpc, json.loads(file.read())[:1], callbacks={1: voteAndVerify}).live()
def HundredTwoTest( rpc: RPC ) -> None: file: IO[Any] = open("e2e/Vectors/Consensus/Verification/HundredTwo.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) file.close() transactions: Transactions = Transactions.fromJSON(vectors["transactions"]) #Verifies the Transaction is added, it has the right holders, the holders Merit surpasses the threshold, yet it isn't verified. def verify() -> None: for tx in transactions.txs: status: Dict[str, Any] = rpc.call("consensus", "getStatus", [tx.hex()]) if set(status["verifiers"]) != set([0, 1]): raise TestError("Meros doesn't have the right list of verifiers for this Transaction.") if status["merit"] != 80: raise TestError("Meros doesn't have the right amount of Merit for this Transaction.") if rpc.call("merit", "getMerit", [0])["merit"] + rpc.call("merit", "getMerit", [1])["merit"] < status["threshold"]: raise TestError("Merit sum of holders is less than the threshold.") if status["verified"]: raise TestError("Meros verified the Transaction which won't have enough Merit by the time the Transaction finalizes.") Liver(rpc, vectors["blockchain"], transactions, callbacks={100: verify}).live()
def MultiInputClaimTest(rpc: RPC) -> None: with open("e2e/Vectors/Transactions/MultiInputClaim.json", "r") as file: vectors: Dict[str, Any] = json.loads(file.read()) transactions: Transactions = Transactions.fromJSON( vectors["transactions"]) Liver(rpc, vectors["blockchain"], transactions).live() Syncer(rpc, vectors["blockchain"], transactions).sync()
def ImpossibleFamilyTest( rpc: RPC ) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Consensus/Families/ImpossibleFamily.json", "r") as file: vectors = json.loads(file.read()) sends: List[Send] = [Send.fromJSON(send) for send in vectors["sends"]] def sendSends() -> None: for s in range(len(sends)): if rpc.meros.liveTransaction(sends[s]) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast a Send.") def verifyPossibleWon() -> None: if rpc.call("consensus", "getStatus", [sends[1].hash.hex()])["verified"]: raise TestError("Meros verified an impossible Transaction.") if not rpc.call("consensus", "getStatus", [sends[0].hash.hex()])["verified"]: raise TestError("Meros didn't verify the only possible Transaction.") Liver( rpc, vectors["blockchain"], Transactions.fromJSON(vectors["transactions"]), callbacks={ 42: sendSends, 48: verifyPossibleWon } ).live()
def ShorterChainMoreWorkTest( rpc: RPC ) -> None: file: IO[Any] = open("e2e/Vectors/Merit/Reorganizations/ShorterChainMoreWork.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[-2].header.hash: raise TestError("Meros didn't request the list of previous BlockHeaders for THIS header.") blockList: List[bytes] = [] b: int = len(alt.blocks) - 3 while b != -1: blockList.append(alt.blocks[b].header.hash) b -= 1 rpc.meros.blockList(blockList) diff = -4 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 = -4 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.") with raises(SuccessError): Liver( rpc, chains["main"], callbacks={ 25: sendAlternateTip } ).live()
def ChainAdvancementTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/Vectors/Merit/BlankBlocks.json", "r") blocks: List[Dict[str, Any]] = json.loads(file.read()) file.close() #Create and execute a Liver/Syncer. Liver(rpc, blocks).live() Syncer(rpc, blocks).sync()
def KeepUnlockedTest(rpc: RPC) -> None: def verifyUnlocked(_: int) -> None: if rpc.call("merit", "getMerit", {"nick": 0})["status"] != "Unlocked": raise TestError("Meros didn't keep Merit unlocked.") with open("e2e/Vectors/Merit/LockedMerit/KeepUnlocked.json", "r") as file: for chain in json.loads(file.read()): Liver(rpc, chain, everyBlock=verifyUnlocked).live() Syncer(rpc, chain).sync()
def KeyChangeTest( rpc: RPC ) -> None: file: IO[Any] = open("e2e/Vectors/Merit/RandomX/KeyChange.json", "r") chain: List[Dict[str, Any]] = json.loads(file.read()) file.close() Liver(rpc, chain).live() Syncer(rpc, chain).sync()