def fromSignedJSON(jsonArg: Dict[str, Any]) -> Any: json: Dict[str, Any] = dict(jsonArg) json["elements"] = list(json["elements"]) json["elements"][0] = dict(json["elements"][0]) json["elements"][1] = dict(json["elements"][1]) json["elements"][0]["holder"] = json["holder"] json["elements"][1]["holder"] = json["holder"] e1: MeritRemovalElement = SignedVerification(bytes(32), 0) if json["elements"][0]["descendant"] == "Verification": e1 = SignedVerification.fromSignedJSON(json["elements"][0]) elif json["elements"][0]["descendant"] == "VerificationPacket": e1 = SignedMeritRemovalVerificationPacket.fromSignedJSON( json["elements"][0]) elif json["elements"][0]["descendant"] == "SendDifficulty": e1 = SignedSendDifficulty.fromSignedJSON(json["elements"][0]) elif json["elements"][0]["descendant"] == "DataDifficulty": e1 = SignedDataDifficulty.fromSignedJSON(json["elements"][0]) e2: MeritRemovalElement = SignedVerification(bytes(32), 0) if json["elements"][1]["descendant"] == "Verification": e2 = SignedVerification.fromSignedJSON(json["elements"][1]) elif json["elements"][1]["descendant"] == "VerificationPacket": e2 = SignedMeritRemovalVerificationPacket.fromSignedJSON( json["elements"][1]) elif json["elements"][1]["descendant"] == "SendDifficulty": e2 = SignedSendDifficulty.fromSignedJSON(json["elements"][1]) elif json["elements"][1]["descendant"] == "DataDifficulty": e2 = SignedDataDifficulty.fromSignedJSON(json["elements"][1]) return SignedMeritRemoval(e1, e2, json["holder"])
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 HundredSixSignedElementsTest(rpc: RPC) -> None: #Solely used to get the genesis Block hash. blockchain: Blockchain = Blockchain() blsPrivKey: PrivateKey = PrivateKey(0) 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(0, 0, 1, sig), SignedDataDifficulty(0, 0, 1, sig) ] for elem in elements: #Handshake with the node. rpc.meros.liveConnect(blockchain.blocks[0].header.hash) #Send the Element. rpc.meros.signedElement(elem) #Sleep for thirty seconds to make sure Meros realizes our connection is dead. sleep(30) #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.")
def OneHundredPercentSketchTest(meros: Meros) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Merit/Sketches/OneHundredPercent.json", "r") as file: vectors = json.loads(file.read()) blockchain: Blockchain = Blockchain.fromJSON(vectors["blockchain"]) meros.liveConnect(blockchain.blocks[0].header.hash) meros.syncConnect(blockchain.blocks[0].header.hash) header: bytes = meros.liveBlockHeader(blockchain.blocks[1].header) meros.handleBlockBody(blockchain.blocks[1]) if meros.live.recv() != header: raise TestError( "Meros didn't broadcast a BlockHeader for a Block it just added.") for data in vectors["datas"]: if meros.liveTransaction(Data.fromJSON(data)) != meros.live.recv(): raise TestError("Meros didn't broadcast back a Data Transaction.") for verif in vectors["verifications"]: if meros.signedElement( SignedVerification.fromSignedJSON(verif)) != meros.live.recv(): raise TestError("Meros didn't broadcast back a Verification.") header = meros.liveBlockHeader(blockchain.blocks[2].header) meros.handleBlockBody(blockchain.blocks[2]) if meros.live.recv() != header: raise TestError( "Meros didn't broadcast a BlockHeader for a Block it just added.")
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 signElement(elem: Element) -> Signature: if isinstance(elem, Verification): verif: SignedVerification = SignedVerification(elem.hash, elem.holder) verif.sign(elem.holder, PrivateKey(elem.holder)) return verif.signature if isinstance(elem, SignedMeritRemovalVerificationPacket): return elem.signature if isinstance(elem, SendDifficulty): sendDiff: SignedSendDifficulty = SignedSendDifficulty( elem.difficulty, elem.nonce) sendDiff.sign(elem.holder, PrivateKey(elem.holder)) return sendDiff.signature if isinstance(elem, DataDifficulty): dataDiff: SignedDataDifficulty = SignedDataDifficulty( elem.difficulty, elem.nonce) dataDiff.sign(elem.holder, PrivateKey(elem.holder)) return dataDiff.signature if isinstance(elem, MeritRemoval): result: Signature = signElement(elem.e2) if not elem.partial: result = Signature.aggregate([result, signElement(elem.e1)]) return result raise GenerationError( "Tried to sign an Element in a Block we didn't recognize the type of.")
def MissingOneSketchTest(meros: Meros) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Merit/Sketches/MissingOne.json", "r") as file: vectors = json.loads(file.read()) blockchain: Blockchain = Blockchain.fromJSON(vectors["blockchain"]) meros.liveConnect(blockchain.blocks[0].header.hash) meros.syncConnect(blockchain.blocks[0].header.hash) header: bytes = meros.liveBlockHeader(blockchain.blocks[1].header) meros.handleBlockBody(blockchain.blocks[1]) if meros.live.recv() != header: raise TestError( "Meros didn't broadcast a BlockHeader for a Block it just added.") for data in vectors["datas"]: if meros.liveTransaction(Data.fromJSON(data)) != meros.live.recv(): raise TestError("Meros didn't broadcast back a Data Transaction.") for verif in vectors["verifications"]: if meros.signedElement( SignedVerification.fromSignedJSON(verif)) != meros.live.recv(): raise TestError("Meros didn't broadcast back a Verification.") header = meros.liveBlockHeader(blockchain.blocks[2].header) meros.handleBlockBody(blockchain.blocks[2], 1) if MessageType(meros.sync.recv()[0]) != MessageType.SketchHashRequests: raise TestError("Meros didn't request the packet it's missing.") meros.packet(VerificationPacket.fromJSON(vectors["packet"])) if meros.live.recv() != header: raise TestError( "Meros didn't broadcast a BlockHeader for a Block it just added.")
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 createSend(rpc: RPC, last: Union[Claim, Send], toAddress: str) -> Send: funded: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32) if isinstance(last, Claim): send: Send = Send([(last.hash, 0)], [(decodeAddress(toAddress), 1), (funded.get_verifying_key(), last.amount - 1)]) else: send: Send = Send( [(last.hash, 1)], [(decodeAddress(toAddress), 1), (funded.get_verifying_key(), last.outputs[1][1] - 1)]) send.sign(funded) send.beat(SpamFilter(3)) sleep(65) rpc.meros.liveConnect(Blockchain().blocks[0].header.hash) if rpc.meros.liveTransaction(send) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast back a Send.") sv: SignedVerification = SignedVerification(send.hash) sv.sign(0, PrivateKey(0)) if rpc.meros.signedElement(sv) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast back a Verification.") return send
def VUnknownSignedTest(rpc: RPC) -> None: file: IO[Any] = open("e2e/Vectors/Merit/BlankBlocks.json", "r") chain: Blockchain = Blockchain.fromJSON(json.loads(file.read())) file.close() #Send a single block so we have a miner. rpc.meros.liveConnect(chain.blocks[0].header.hash) rpc.meros.syncConnect(chain.blocks[0].header.hash) header: bytes = rpc.meros.liveBlockHeader(chain.blocks[1].header) if MessageType(rpc.meros.sync.recv()[0]) != MessageType.BlockBodyRequest: raise TestError("Meros didn't ask for the body.") rpc.meros.blockBody(chain.blocks[1]) if rpc.meros.live.recv() != header: raise TestError("Meros didn't broadcast the header.") #Create a valid Data. #Uneccessary at this time, but good preparation for the future. privKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32) data: Data = Data(bytes(32), privKey.get_verifying_key().to_bytes()) data.sign(privKey) data.beat(SpamFilter(5)) #Sign the Data. verif: SignedVerification = SignedVerification(data.hash) verif.sign(0, PrivateKey(0)) #Run twice. The first shouldn't send the Transaction. The second should. for i in range(2): rpc.meros.signedElement(verif) if MessageType( rpc.meros.sync.recv()[0]) != MessageType.TransactionRequest: raise TestError("Meros didn't request the transaction.") if i == 0: #When we send DataMissing, we should be disconnected within a few seconds. rpc.meros.dataMissing() start: int = int(time()) try: rpc.meros.sync.recv() except Exception: #More than a few seconds is allowed as Meros's own SyncRequest must timeout. if int(time()) - start > 10: raise TestError( "Meros didn't disconnect us for sending a Verification of a non-existent Transaction." ) #Clear our invalid connections. rpc.meros.live.connection.close() rpc.meros.sync.connection.close() sleep(65) #Init new ones. rpc.meros.liveConnect(chain.blocks[0].header.hash) rpc.meros.syncConnect(chain.blocks[0].header.hash) else: rpc.meros.syncTransaction(data) sleep(2) if not rpc.call("consensus", "getStatus", [data.hash.hex()])["verifiers"]: raise TestError("Meros didn't add the Verification.")
def sendDatas() -> None: for data in datas: if rpc.meros.liveTransaction(data) != rpc.meros.live.recv(): raise TestError("Meros didn't send back the Data.") #Send the beaten Data's descendant's verification. if rpc.meros.signedElement(SignedVerification.fromSignedJSON(vectors["verification"])) != rpc.meros.live.recv(): raise TestError("Meros didn't send back the SignedVerification.")
def verify(rpc: RPC, txHash: bytes, nick: int = 0, mr: bool = False) -> None: sv: SignedVerification = SignedVerification(txHash) sv.sign(nick, PrivateKey(nick)) temp: bytes = rpc.meros.signedElement(sv) if mr: if MessageType( rpc.meros.live.recv()[0]) != MessageType.SignedMeritRemoval: raise TestError("Meros didn't create a MeritRemoval.") elif temp != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast back a Verification.")
def sendDatas() -> None: for data in datas: if rpc.meros.liveTransaction(data) != rpc.meros.live.recv(): raise TestError("Meros didn't send back the Data.") #Send the winning descendant Data's verification. verif: SignedVerification = SignedVerification.fromSignedJSON( vectors["verification"]) if rpc.meros.signedElement(verif) != rpc.meros.live.recv(): raise TestError("Meros didn't send back the SignedVerification.") #The Liver thinks we sent this packet, so it shouldn't have to. #That said, that'd only be true if this was included in the Sketcher. #As its parent is unmentioned, it won't be. del rpc.meros.sentVerifs[verif.hash]
def verifyUnarchivedMerit() -> None: #Send the verification which won't be archived. if rpc.meros.signedElement( SignedVerification.fromSignedJSON( vectors["verification"])) != rpc.meros.live.recv(): raise TestError("Meros didn't send back the SignedVerification.") status: Dict[str, Any] = rpc.call("consensus", "getStatus", {"hash": vectors["transaction"]}) if sorted(status["verifiers"]) != [0, 1]: raise TestError( "Status didn't include verifiers which have yet to be archived." ) if status["merit"] != 7: raise TestError( "Status didn't include Merit which has yet to be archived.")
def HundredSixSignedElementsTest( rpc: RPC ) -> None: #Solely used to get the genesis Block hash. blockchain: Blockchain = Blockchain() edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32) blsPrivKey: PrivateKey = PrivateKey(0) sig: Signature = blsPrivKey.sign(bytes()) #Create a Data for the Verification. data: Data = Data(bytes(32), edPrivKey.get_verifying_key()) data.sign(edPrivKey) data.beat(SpamFilter(5)) #Create a signed Verification, SendDifficulty, and DataDifficulty. elements: List[SignedElement] = [ SignedVerification(data.hash, 1, sig), SignedSendDifficulty(0, 0, 1, sig), SignedDataDifficulty(0, 0, 1, sig) ] dataSent: bool = False for elem in elements: #Handshake with the node. rpc.meros.liveConnect(blockchain.blocks[0].header.hash) #Send the Data if we have yet to. if not dataSent: if rpc.meros.liveTransaction(data) != rpc.meros.live.recv(): raise TestError("Data wasn't rebroadcasted.") dataSent = True #Send the Element. rpc.meros.signedElement(elem) #Sleep for thirty seconds to make sure Meros realizes our connection is dead. sleep(30) #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.")
def signElement(elem: Element) -> Signature: if isinstance(elem, Verification): verif: SignedVerification = SignedVerification(elem.hash, elem.holder) verif.sign(elem.holder, PrivateKey(elem.holder)) return verif.signature if isinstance(elem, SendDifficulty): sendDiff: SignedSendDifficulty = SignedSendDifficulty( elem.difficulty, elem.nonce) sendDiff.sign(elem.holder, PrivateKey(elem.holder)) return sendDiff.signature if isinstance(elem, DataDifficulty): dataDiff: SignedDataDifficulty = SignedDataDifficulty( elem.difficulty, elem.nonce) dataDiff.sign(elem.holder, PrivateKey(elem.holder)) return dataDiff.signature raise GenerationError( "Tried to sign an Element in a Block we didn't recognize the type of.")
def verify(rpc: RPC, tx: bytes) -> None: sv: SignedVerification = SignedVerification(tx) sv.sign(0, PrivateKey(0)) if rpc.meros.signedElement(sv) != rpc.meros.live.recv(): raise TestError("Meros didn't send back a Verification.")
#Children. One which will have a Verification, one which won't. sends += [ Send([(sends[1].hash, 0)], [(edPubKey, claim.amount // 2)]), Send([(sends[1].hash, 1)], [(edPubKey, claim.amount // 2)]) ] #Send which spend the remaining descendant of the beaten Transaction. sends.append(Send([(sends[2].hash, 0)], [(bytes(32), claim.amount // 2)])) for s in range(len(sends)): sends[s].sign(edPrivKey) sends[s].beat(sendFilter) if s < 3: transactions.add(sends[s]) verif: SignedVerification = SignedVerification(sends[2].hash, 1) verif.sign(1, PrivateKey(1)) merit.add( PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200, packets=[ VerificationPacket(sends[0].hash, [0]), VerificationPacket(sends[1].hash, [1]) ]).finish(0, merit)) merit.add( PrototypeBlock(merit.blockchain.blocks[-1].header.time + 1200, packets=[VerificationPacket(sends[2].hash, [0])]).finish(0, merit)) for _ in range(4):
def PartialArchiveTest(rpc: RPC) -> None: vectors: Dict[str, Any] with open("e2e/Vectors/Consensus/Verification/PartialArchive.json", "r") as file: vectors = json.loads(file.read()) data: Data = Data.fromJSON(vectors["data"]) svs: List[SignedVerification] = [ SignedVerification.fromSignedJSON(vectors["verifs"][0]), SignedVerification.fromSignedJSON(vectors["verifs"][1]) ] key: PrivateKey = PrivateKey( bytes.fromhex(rpc.call("personal", "getMiner"))) def sendDataAndVerifications() -> None: if rpc.meros.liveTransaction(data) != rpc.meros.live.recv(): raise TestError( "Meros didn't rebroadcast a Transaction we sent it.") for sv in svs: if rpc.meros.signedElement(sv) != rpc.meros.live.recv(): raise TestError( "Meros didn't rebroadcast a SignedVerification we sent it." ) #As we don't have a quality RPC route for this, we need to use getTemplate. if bytes.fromhex( rpc.call("merit", "getBlockTemplate", [key.toPublicKey().serialize().hex() ])["header"])[36:68] != BlockHeader.createContents( [VerificationPacket(data.hash, [0, 1])]): raise TestError( "New Block template doesn't have a properly created packet.") def verifyRecreation() -> None: template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate", [key.toPublicKey().serialize().hex()]) if bytes.fromhex( template["header"])[36:68] != BlockHeader.createContents( [VerificationPacket(data.hash, [1])]): raise TestError( "New Block template doesn't have a properly recreated packet.") #Mining it further verifies the internal state. header: bytes = bytes.fromhex(template["header"]) proof: int = 0 sig: bytes while True: initial: bytes = RandomX(header + proof.to_bytes(4, byteorder="little")) sig = key.sign(initial).serialize() final: bytes = RandomX(initial + sig) if (int.from_bytes(final, "little") * template["difficulty"]) < int.from_bytes( bytes.fromhex("FF" * 32), "little"): break proof += 1 rpc.call("merit", "publishBlock", [ template["id"], (header + proof.to_bytes(4, byteorder="little") + sig).hex() ]) raise SuccessError( "Stop Liver from trying to verify the vector chain which doesn't have this Block." ) #We may not want to use Liver here. #There's a very small Block count and we can't let it terminate (hence the SE). with raises(SuccessError): Liver(rpc, vectors["blockchain"], callbacks={ 2: sendDataAndVerifications, 3: verifyRecreation }).live()
def finish(self, keepUnlocked: int, existing: Merit) -> Block: genesis: bytes = existing.blockchain.genesis prev: BlockHeader = existing.blockchain.blocks[-1].header diff: int = existing.blockchain.difficulty() #Create the signatures for every packet/element. signatures: List[Signature] = [] for packet in self.packets: for holder in packet.holders: verif: SignedVerification = SignedVerification( packet.hash, holder) verif.sign(holder, PrivateKey(holder)) signatures.append(verif.signature) for element in self.elements: signatures.append(signElement(element)) #Only add the Data Verification if: #1) We're supposed to make sure Merit Holders are always Unlocked #2) The last Block created a Data #3) The Merit Holder has Merit. if (keepUnlocked != 0) and (prev.last != genesis): #Create the Data from the last Block. blockData: Data = Data(genesis, prev.hash) #Create Verifications for said Data with every Private Key. #Ensures no one has their Merit locked. #pylint: disable=unnecessary-comprehension self.packets.append(VerificationPacket(blockData.hash, [])) for i in range(keepUnlocked): if ( #Miners who are just being created don't have Merit. ((i == (keepUnlocked - 1)) and (isinstance(self.minerID, PrivateKey))) or (existing.state.balances[i] == 0)): continue self.packets[-1].holders.append(i) verif: SignedVerification = SignedVerification( blockData.hash, i) verif.sign(i, PrivateKey(i)) signatures.append(verif.signature) #Remove this packet if there's no holders. if not self.packets[-1].holders: del self.packets[-1] #Set the aggregate. aggregate = Signature.aggregate(signatures) #Create the actual Block. minerID: Union[bytes, int] = 0 if isinstance(self.minerID, int): minerID = self.minerID else: minerID = self.minerID.toPublicKey().serialize() result: Block = Block( BlockHeader( 0, prev.hash, BlockHeader.createContents(self.packets, self.elements), len(self.packets), bytes(4), BlockHeader.createSketchCheck(bytes(4), self.packets), minerID, self.time), BlockBody(self.packets, self.elements, aggregate)) if isinstance(self.minerID, int): result.mine(PrivateKey(self.minerID), diff) else: result.mine(self.minerID, diff) return result
for i in range(4): merit.add(Block.fromJSON(blankBlocks[i])) #Create the Datas. datas: List[Data] = [Data(bytes(32), edPubKey.to_bytes())] datas.append(Data(datas[-1].hash, bytes(1))) for data in datas: data.sign(edPrivKey) data.beat(dataFilter) transactions.add(data) #Verify them in unique Blocks. packet: List[VerificationPacket] for data in datas: verif: SignedVerification = SignedVerification(data.hash) verif.sign(0, blsPrivKey) packet = [VerificationPacket(data.hash, [0])] block = Block( BlockHeader( 0, merit.blockchain.last(), BlockHeader.createContents(packet), 1, bytes(4), BlockHeader.createSketchCheck(bytes(4), packet), 0, merit.blockchain.blocks[-1].header.time + 1200 ), BlockBody(packet, [], verif.signature)
def EightyEightTest( rpc: RPC ) -> None: edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32) edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key() blsPrivKey: PrivateKey = PrivateKey(0) blsPubKey: str = blsPrivKey.toPublicKey().serialize().hex() file: IO[Any] = open("e2e/Vectors/Merit/BlankBlocks.json", "r") blocks: List[Dict[str, Any]] = json.loads(file.read()) file.close() merit: Merit = Merit() dataFilter: SpamFilter = SpamFilter(5) #Handshake with the node. rpc.meros.liveConnect(merit.blockchain.blocks[0].header.hash) rpc.meros.syncConnect(merit.blockchain.blocks[0].header.hash) #Send the first Block. block: Block = Block.fromJSON(blocks[0]) merit.blockchain.add(block) rpc.meros.liveBlockHeader(block.header) #Handle sync requests. reqHash: bytes = bytes() while True: msg: bytes = rpc.meros.sync.recv() if MessageType(msg[0]) == MessageType.BlockBodyRequest: reqHash = msg[1 : 33] if reqHash != block.header.hash: raise TestError("Meros asked for a Block Body that didn't belong to the Block we just sent it.") #Send the BlockBody. rpc.meros.blockBody(block) break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) if MessageType(rpc.meros.live.recv()[0]) != MessageType.BlockHeader: raise TestError("Meros didn't broadcast the Block Header it just added.") #Create two Datas. datas: List[Data] = [Data(bytes(32), edPubKey.to_bytes())] datas.append(Data(datas[0].hash, b"Hello there! General Kenobi.")) for data in datas: #Sign them and have them beat the spam filter. data.sign(edPrivKey) data.beat(dataFilter) #Transmit them. rpc.meros.liveTransaction(data) #Verify both. verifs: List[SignedVerification] = [ SignedVerification(datas[0].hash), SignedVerification(datas[1].hash) ] for verif in verifs: verif.sign(0, blsPrivKey) #Only transmit the second. rpc.meros.signedElement(verifs[1]) sleep(0.5) #Verify the block template has no verifications. if bytes.fromhex( rpc.call("merit", "getBlockTemplate", [blsPubKey])["header"] )[36 : 68] != bytes(32): raise TestError("Block template has Verification Packets.") #Transmit the first signed verification. rpc.meros.signedElement(verifs[0]) sleep(0.5) #Verify the block template has both verifications. template: Dict[str, Any] = rpc.call("merit", "getBlockTemplate", [blsPubKey]) template["header"] = bytes.fromhex(template["header"]) packets: List[VerificationPacket] = [VerificationPacket(datas[0].hash, [0]), VerificationPacket(datas[1].hash, [0])] if template["header"][36 : 68] != BlockHeader.createContents(packets): raise TestError("Block template doesn't have both Verification Packets.") #Mine the Block. block = Block( BlockHeader( 0, block.header.hash, BlockHeader.createContents(packets), 1, template["header"][-43 : -39], BlockHeader.createSketchCheck(template["header"][-43 : -39], packets), 0, int.from_bytes(template["header"][-4:], byteorder="little") ), BlockBody( packets, [], Signature.aggregate([verifs[0].signature, verifs[1].signature]) ) ) if block.header.serializeHash()[:-4] != template["header"]: raise TestError("Failed to recreate the header.") if block.body.serialize( block.header.sketchSalt, len(packets) ) != bytes.fromhex(template["body"]): raise TestError("Failed to recreate the body.") block.mine(blsPrivKey, merit.blockchain.difficulty()) merit.blockchain.add(block) rpc.call( "merit", "publishBlock", [ template["id"], ( template["header"] + block.header.proof.to_bytes(4, byteorder="little") + block.header.signature + block.body.serialize(block.header.sketchSalt, len(packets)) ).hex() ] ) verifyBlockchain(rpc, merit.blockchain)
def HundredFiftyFiveTest(rpc: RPC) -> None: 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() ] blsPrivKey: PrivateKey = PrivateKey( bytes.fromhex(rpc.call("personal", "getMiner"))) blsPubKey: bytes = blsPrivKey.toPublicKey().serialize() blockchain: Blockchain = Blockchain() 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) rpc.call("merit", "publishBlock", [template["id"], block.serialize().hex()]) if MessageType(rpc.meros.live.recv()[0]) != MessageType.BlockHeader: raise TestError("Meros didn't broadcast the Block we just published.") #Ignore the Verification for the Block's Data. if MessageType(rpc.meros.live.recv()[0]) != MessageType.SignedVerification: raise TestError( "Meros didn't send the SignedVerification for the Block's Data.") datas: List[Data] = [ Data(bytes(32), edPubKeys[0].to_bytes()), Data(bytes(32), edPubKeys[1].to_bytes()) ] for d in range(len(datas)): 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.")
blsPubKey: PublicKey = blsPrivKey.toPublicKey() spamFilter: SpamFilter = SpamFilter(5) #Create the initial Data and two competing Datas. datas: List[Data] = [Data(bytes(32), edPubKey.to_bytes())] datas.append(Data(datas[0].hash, b"Initial Data.")) datas.append(Data(datas[0].hash, b"Second Data.")) for data in datas: data.sign(edPrivKey) data.beat(spamFilter) #Create Verifications for all 3. verifs: List[SignedVerification] = [] for data in datas: verifs.append(SignedVerification(data.hash, 0)) verifs[-1].sign(0, blsPrivKey) #Create a MeritRemoval out of the conflicting Verifications. mr: SignedMeritRemoval = SignedMeritRemoval(verifs[1], verifs[2]) #Create a MeritRemoval with random keys. packeted: SignedMeritRemoval = SignedMeritRemoval( SignedMeritRemovalVerificationPacket( SignedVerificationPacket(verifs[1].hash), [ blsPubKey.serialize(), PrivateKey(1).toPublicKey().serialize(), PrivateKey(2).toPublicKey().serialize() ], Signature.aggregate([
#BLS keys. blsPrivKey: PrivateKey = PrivateKey(blake2b(b'\0', digest_size=32).digest()) blsPubKey: PublicKey = blsPrivKey.toPublicKey() #Add 5 Blank Blocks. for i in range(5): merit.add(Block.fromJSON(blankBlocks[i])) #Create the Data. data: Data = Data(bytes(32), edPubKey.to_bytes()) data.sign(edPrivKey) data.beat(dataFilter) transactions.add(data) #Verify it. verif: SignedVerification = SignedVerification(data.hash) verif.sign(0, blsPrivKey) #Generate another 6 Blocks. #Next block should have a packet. block: Block = Block( BlockHeader( 0, merit.blockchain.last(), BlockHeader.createContents([VerificationPacket(verif.hash, [0])]), 1, bytes(4), BlockHeader.createSketchCheck(bytes(4), [VerificationPacket(verif.hash, [0])]), 0, merit.blockchain.blocks[-1].header.time + 1200), BlockBody([VerificationPacket(verif.hash, [0])], [], verif.signature)) for _ in range(6): #Mine it.
dataFilter: SpamFilter = SpamFilter(5) edPrivKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32) edPubKey: bytes = edPrivKey.get_verifying_key() proto: PrototypeChain = PrototypeChain(40, keepUnlocked=True) proto.add(1) datas: List[Data] = [Data(bytes(32), edPubKey)] for d in range(2): datas.append(Data(datas[0].hash, d.to_bytes(1, "little"))) for data in datas: data.sign(edPrivKey) data.beat(dataFilter) verif: SignedVerification = SignedVerification(datas[1].hash) verif.sign(0, PrivateKey(0)) proto.add( packets=[ VerificationPacket(datas[0].hash, [0]), VerificationPacket(datas[2].hash, [1]) ] ) for _ in range(5): proto.add() with open("e2e/Vectors/Consensus/Families/UnmentionedBeatMentioned.json", "w") as vectors: vectors.write(json.dumps({ "blockchain": proto.toJSON(), "datas": [data.toJSON() for data in datas],
#Create the Datas. datas: List[Data] = [Data(bytes(32), edPubKey.to_bytes())] datas.append(Data(datas[-1].hash, bytes(1))) datas.append(Data(datas[-1].hash, bytes(1))) datas.append(Data(datas[-1].hash, bytes(1))) for data in datas: data.sign(edPrivKey) data.beat(dataFilter) transactions.add(data) #Verify them. verifs: List[List[SignedVerification]] = [] for data in datas: verifs.append( [SignedVerification(data.hash), SignedVerification(data.hash)]) for v in range(2): verifs[-1][v].sign(v, blsPrivKeys[v]) #Create the packets. packets: List[SignedVerificationPacket] = [] for packet in verifs: packets.append( SignedVerificationPacket( packet[0].hash, [0, 1], Signature.aggregate([packet[0].signature, packet[1].signature]))) #Create Blocks containing these packets. for packet in packets: block = Block(
block: Block = Block( BlockHeader(0, blockchain.last(), bytes(32), 1, bytes(4), bytes(32), blsPubKeys[1].serialize(), blockchain.blocks[-1].header.time + 1200), BlockBody()) block.mine(blsPrivKeys[1], blockchain.difficulty()) blockchain.add(block) print("Generated Hundred Forty Two Block " + str(len(blockchain.blocks)) + ".") #Create a Data and verify it by both parties. data: Data = Data(bytes(32), edPubKey.to_bytes()) data.sign(edPrivKey) data.beat(spamFilter) transactions.add(data) verifs: List[SignedVerification] = [ SignedVerification(data.hash), SignedVerification(data.hash) ] verifs[0].sign(0, blsPrivKeys[0]) verifs[1].sign(1, blsPrivKeys[1]) packets: List[VerificationPacket] = [VerificationPacket(data.hash, [0])] block = Block( BlockHeader(0, blockchain.last(), BlockHeader.createContents(packets), 1, bytes(4), BlockHeader.createSketchCheck(bytes(4), packets), 1, blockchain.blocks[-1].header.time + 1200), BlockBody(packets, [], verifs[0].signature)) for _ in range(6): block.mine(blsPrivKeys[1], blockchain.difficulty()) blockchain.add(block) print("Generated Hundred Forty Two Block " + str(len(blockchain.blocks)) +
for i in range(1): merit.add(Block.fromJSON(blankBlocks[i])) #Create the Data and a successor. first: Data = Data(bytes(32), edPubKey.to_bytes()) first.sign(edPrivKey) first.beat(dataFilter) transactions.add(first) second: Data = Data(first.hash, bytes(1)) second.sign(edPrivKey) second.beat(dataFilter) transactions.add(second) #Verify them. firstVerif: SignedVerification = SignedVerification(first.hash) firstVerif.sign(0, blsPrivKey) secondVerif: SignedVerification = SignedVerification(second.hash) secondVerif.sign(0, blsPrivKey) packets: List[VerificationPacket] = [ VerificationPacket(first.hash, [0]), VerificationPacket(second.hash, [0]), ] #Generate another 6 Blocks. #Next block should have the packets. block: Block = Block( BlockHeader( 0,
block.mine(blsPrivKey, blockchain.difficulty()) #Add it. blockchain.add(block) print("Generated Invalid Competing Block " + str(len(blockchain.blocks)) + ".") #Create a Data using a bogus input. data: Data = Data(bytes.fromhex("11" * 32), bytes(1)) transactions.add(data) #Create a competing Data using the same input. competingData: Data = Data(bytes.fromhex("11" * 32), bytes(2)) transactions.add(competingData) #Verify the Datas. verif: SignedVerification = SignedVerification(data.hash) verif.sign(0, blsPrivKey) competingVerif: SignedVerification = SignedVerification(competingData.hash) competingVerif.sign(0, blsPrivKey) #Create a MeritRemoval out of the conflicting Verifications. mr: SignedMeritRemoval = SignedMeritRemoval(verif, competingVerif) #Generate a Block containing the MeritRemoval. block = Block( BlockHeader(0, blockchain.last(), BlockHeader.createContents([], [mr]), 1, bytes(4), BlockHeader.createSketchCheck(bytes(4), []), 0, blockchain.blocks[-1].header.time + 1200), BlockBody([], [mr], mr.signature)) #Mine it.