def fromJSON(json: Dict[str, Dict[str, Any]]) -> Any: result = Transactions() for tx in json: if json[tx]["descendant"] == "Claim": result.add(Claim.fromJSON(json[tx])) elif json[tx]["descendant"] == "Send": result.add(Send.fromJSON(json[tx])) elif json[tx]["descendant"] == "Data": result.add(Data.fromJSON(json[tx])) else: raise Exception("JSON has an unsupported Transaction type: " + json[tx]["descendant"]) return result
def DataTest(rpc: RPC) -> None: #Create the Spam Filter. filter: SpamFilter = SpamFilter( bytes.fromhex( "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" )) #Create the Data. data: Data = Data(pubKey.to_bytes().rjust(48, b'\0'), b"Hello There! General Kenobi.") data.sign(privKey) data.beat(filter) #Handshake with the node. rpc.meros.connect(254, 254, 0) #Send the Data. rpc.meros.transaction(data) #Verify the Data. verifyTransaction(rpc, data)
#Ed25519 keys. edKeys: List[ed25519.SigningKey] = [] for i in range(6): edKeys.append(ed25519.SigningKey(i.to_bytes(1, byteorder="big") * 32)) #Add a single Block to create Merit. bbFile: IO[Any] = open("python_tests/Vectors/Merit/BlankBlocks.json", "r") blocks: List[Dict[str, Any]] = json.loads(bbFile.read()) blockchain.add(Block.fromJSON(blocks[0])) bbFile.close() #Create a Data per key. datas: List[Data] = [] for edPrivKey in edKeys: datas.append( Data(edPrivKey.get_verifying_key().to_bytes().rjust(48, b'\0'), bytes())) datas[-1].sign(edPrivKey) datas[-1].beat(consensus.dataFilter) #Create 1 Verification per Data. verifs: List[SignedVerification] = [] for d in range(len(datas)): verifs.append(SignedVerification(datas[d].hash)) verifs[-1].sign(privKey, d) if d < 3: consensus.add(verifs[-1]) #Create a MeritRemoval off the last one. sv: SignedVerification = SignedVerification(b'\0' * 48) sv.sign(privKey, 5) removal: SignedMeritRemoval = SignedMeritRemoval(
#Ed25519 keys. edPrivKey: ed25519.SigningKey = ed25519.SigningKey(b'\0' * 32) edPubKey: ed25519.VerifyingKey = edPrivKey.get_verifying_key() #BLS keys. blsPrivKey: blspy.PrivateKey = blspy.PrivateKey.from_seed(b'\0') blsPubKey: blspy.PublicKey = blsPrivKey.get_public_key() #Add 13 Blank Blocks. for i in range(13): merit.add(transactions, consensus, Block.fromJSON(blankBlocks[i])) #Create the Data. data: Data = Data( edPubKey.to_bytes().rjust(48, b'\0'), bytes() ) data.sign(edPrivKey) data.beat(consensus.dataFilter) data.verified = True transactions.add(data) #Verify it. verif: SignedVerification = SignedVerification(data.hash) verif.sign(blsPrivKey, 0) consensus.add(verif) #Generate another 6 Blocks. #Next block should have a record. block: Block = Block( BlockHeader(
def MRPALiveTest(rpc: RPC) -> None: file: IO[Any] = open( "python_tests/Vectors/Consensus/MeritRemoval/PendingActions.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) #Datas. datas: List[Data] = [] for data in vectors["datas"]: datas.append(Data.fromJSON(data)) #SignedVerifications. verifs: List[SignedVerification] = [] for verif in vectors["verifications"]: verifs.append(SignedVerification.fromJSON(verif)) #Removal. removal: SignedMeritRemoval = SignedMeritRemoval.fromJSON( vectors["removal"]) #Consensus. consensus: Consensus = Consensus( bytes.fromhex( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ), bytes.fromhex( "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" ), ) consensus.add(verifs[0]) consensus.add(verifs[1]) consensus.add(verifs[2]) consensus.add(removal) #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) - 2) hash: bytes = bytes() msg: bytes = bytes() height: int = 0 while True: msg = rpc.meros.recv() if MessageType(msg[0]) == MessageType.Syncing: rpc.meros.acknowledgeSyncing() elif MessageType(msg[0]) == MessageType.GetBlockHash: height = int.from_bytes(msg[1:5], byteorder="big") if height == 0: rpc.meros.blockHash(blockchain.blocks[1].header.hash) 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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.SyncingOver: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #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("transactions", "getMerit", [data.hash.hex()]) != { "merit": 100 }: raise TestError( "Meros didn't verify Transactions with received Verifications." ) #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 100 Merit. for data in datas: if rpc.call("transactions", "getMerit", [data.hash.hex()]) != { "merit": 0 }: raise TestError( "Meros didn't revert pending actions of a malicious MeritHolder." ) #Send the next Block. rpc.meros.blockHeader(blockchain.blocks[-2].header) while True: msg = rpc.meros.recv() if MessageType(msg[0]) == MessageType.Syncing: rpc.meros.acknowledgeSyncing() elif MessageType(msg[0]) == MessageType.GetBlockHash: height = int.from_bytes(msg[1:5], byteorder="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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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.SyncingOver: pass elif MessageType(msg[0]) == MessageType.BlockHeader: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #Update the MeritRemoval's nonce. removal.nonce = 3 #Verify the Datas have the Merit they should. for d in range(len(datas)): if rpc.call("transactions", "getMerit", [datas[d].hash.hex()]) != { "merit": 100 if d < 3 else 0 }: raise TestError( "Meros didn't apply reverted pending actions of a malicious MeritHolder." ) #Verify the MeritRemoval is now accessible with a nonce of 3. verifyMeritRemoval(rpc, 4, 200, removal, True) #Archive the MeritRemoval. rpc.meros.blockHeader(blockchain.blocks[-1].header) while True: msg = rpc.meros.recv() if MessageType(msg[0]) == MessageType.Syncing: rpc.meros.acknowledgeSyncing() elif MessageType(msg[0]) == MessageType.GetBlockHash: height = int.from_bytes(msg[1:5], byteorder="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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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.SyncingOver: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #Verify the Blockchain. verifyBlockchain(rpc, blockchain) #Verify the Consensus. verifyConsensus(rpc, consensus) #Verify the MeritRemoval again. verifyMeritRemoval(rpc, 4, 200, removal, False)
def MRPLiveTest(rpc: RPC) -> None: file: IO[Any] = open( "python_tests/Vectors/Consensus/MeritRemoval/Partial.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) #Data. data: Data = Data.fromJSON(vectors["data"]) #Consensus. consensus: Consensus = Consensus( bytes.fromhex( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ), bytes.fromhex( "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" )) #MeritRemoval. removal: PartiallySignedMeritRemoval = PartiallySignedMeritRemoval.fromJSON( vectors["removal"]) consensus.add(removal.e1) consensus.add(removal) #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) - 1) sentLast: bool = False hash: bytes = bytes() msg: bytes = bytes() while True: msg = 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], byteorder="big") if height == 0: rpc.meros.blockHash(blockchain.blocks[2].header.hash) 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: if msg[1:49] != removal.holder: raise TestError( "Meros asked for an Element from an unknown MeritHolder.") if int.from_bytes(msg[49:53], byteorder="big") != 0: raise TestError( "Meros asked for an Element not mentioned in a record.") rpc.meros.element(removal.e1) elif MessageType(msg[0]) == MessageType.TransactionRequest: sentLast = True if msg[1:49] != data.hash: raise TestError("Meros asked for a Transaction not mentioned.") rpc.meros.transaction(data) elif MessageType(msg[0]) == MessageType.SyncingOver: if sentLast == True: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #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) #Send the final Block. rpc.meros.blockHeader(blockchain.blocks[-1].header) while True: msg = rpc.meros.recv() if MessageType(msg[0]) == MessageType.Syncing: rpc.meros.acknowledgeSyncing() elif MessageType(msg[0]) == MessageType.GetBlockHash: height = int.from_bytes(msg[1:5], byteorder="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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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.SyncingOver: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #Verify the Blockchain. verifyBlockchain(rpc, blockchain) #Verify the MeritRemoval again. verifyMeritRemoval(rpc, 2, 200, removal, False) #Verify the Consensus. verifyConsensus(rpc, consensus)
def MRSNCauseTest(rpc: RPC) -> None: file: IO[Any] = open( "python_tests/Vectors/Consensus/MeritRemoval/SameNonce.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) #Data. data: Data = Data.fromJSON(vectors["data"]) #MeritRemoval. removal: SignedMeritRemoval = SignedMeritRemoval.fromJSON( vectors["removal"]) #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) - 1) hash: bytes = bytes() msg: bytes = bytes() height: int = 0 while True: msg = rpc.meros.recv() if MessageType(msg[0]) == MessageType.Syncing: rpc.meros.acknowledgeSyncing() elif MessageType(msg[0]) == MessageType.GetBlockHash: height = int.from_bytes(msg[1:5], byteorder="big") if height == 0: rpc.meros.blockHash(blockchain.blocks[1].header.hash) 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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.SyncingOver: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #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) #Send the final Block. rpc.meros.blockHeader(blockchain.blocks[-1].header) while True: msg = rpc.meros.recv() if MessageType(msg[0]) == MessageType.Syncing: rpc.meros.acknowledgeSyncing() elif MessageType(msg[0]) == MessageType.GetBlockHash: height = int.from_bytes(msg[1:5], byteorder="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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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.SyncingOver: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #Verify the Blockchain. verifyBlockchain(rpc, blockchain) #Verify the MeritRemoval again. verifyMeritRemoval(rpc, 1, 100, removal, False)
def VParsable(rpc: RPC) -> None: file: IO[Any] = open( "python_tests/Vectors/Consensus/Verification/Parsable.json", "r") vectors: Dict[str, Any] = json.loads(file.read()) #Data. data: Data = Data.fromJSON(vectors["data"]) #Consensus. consensus: Consensus = Consensus( bytes.fromhex( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ), bytes.fromhex( "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" ), ) sv: SignedVerification = SignedVerification.fromJSON( vectors["verification"]) consensus.add(sv) #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 hash: 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], byteorder="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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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: hash = msg[1:49] for block in blockchain.blocks: if block.header.hash == hash: 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.transaction(data) elif MessageType(msg[0]) == MessageType.SyncingOver: if sentLast: break else: raise TestError("Unexpected message sent: " + msg.hex().upper()) #Verify the Blockchain. verifyBlockchain(rpc, blockchain) #Verify the Consensus. verifyConsensus(rpc, consensus) #Playback their messages. rpc.meros.playback()