def from_base64(self, b64_claim: str, is_big_endian: bool = True): try: b64_head, b64_payload, b64_signature, b64_blk_proof = b64_claim.split('.') except ValueError: raise SDKException(ErrorCode.invalid_b64_claim_data) self.__head = Header.from_base64(b64_head) self.__payload = Payload.from_base64(b64_payload) self.__signature = base64.b64decode(b64_signature) self.__blk_proof = BlockchainProof(self.__sdk).from_base64(b64_blk_proof, is_big_endian)
def test_proof(self): proof_node = [{ 'Direction': 'Left', 'TargetHash': '328c513fcfcd715e8ec537ab7d9d3a40a4a0cab6147afb2342b5a45226eaf134' }, { 'Direction': 'Left', 'TargetHash': '3035c97472f112e92ab0f72d0d2d7d5ee36ae4d46aae0c08874cef90f1f32f0c' }, { 'Direction': 'Left', 'TargetHash': '94237b775cb687b15413ada5166fb723ea7f0767fa4ecbf899af5db6932444e5' }, { 'Direction': 'Left', 'TargetHash': 'c8c494ae321875dd94d9622ebb38f013c477edece714f7d68d605b42b0abe09e' }, { 'Direction': 'Left', 'TargetHash': '610f87fbcbdd3b4c316946086d9177f85db5d40b2335f797ab8b869fe0248a90' }, { 'Direction': 'Left', 'TargetHash': '92f41a0485e2591ccd11efd41b9a931fab56349bebe340e9fd81a0281bb1ef73' }, { 'Direction': 'Left', 'TargetHash': 'bcbc040368a66ec9d1dfcf489eb00aaa424e286ac84c53979c325531e9d0ea80' }, { 'Direction': 'Left', 'TargetHash': '84bb65ae876c5cc67c3c57fad08382ba18d0ddd6758e6b37794fd461c173cea4' }] tx_hash = 'c6e2b089a835821916bc612a046e3eaada3c6abc0c274062303384d0a8c71b56' hex_contract_address = '36bb5c053b6b839c8f6b923fe852f91239b9fccc' merkle_root = 'ed7f4d2e91925917d4242b3a59a3f47830d77bca383ffc78e078a1f93ddb62c4' blk_height = 705043 proof = BlockchainProof(tx_hash, hex_contract_address, blk_height, merkle_root, proof_node) self.assertTrue(isinstance(proof, BlockchainProof)) self.assertTrue(proof.validate_blk_proof()) dict_proof = dict(proof) self.assertTrue(isinstance(dict_proof, dict)) proof.merkle_root = 'ed7f4d2e91925917d4242b3a59a3f47830d77bca383ffc78e078a1f93ddb62c5' self.assertFalse(proof.validate_blk_proof())
def generate_blk_proof(self, iss_acct: Account, payer: Account, gas_limit: int, gas_price: int, hex_contract_address: str = ''): if not isinstance(hex_contract_address, str): raise SDKException(ErrorCode.require_str_params) if len(hex_contract_address) != 0: self.__sdk.neo_vm.claim_record( ).hex_contract_address = hex_contract_address tx_hash = self.__sdk.neo_vm.claim_record().commit( self.payload.jti, iss_acct, self.payload.sub, payer, gas_limit, gas_price) sleep(12) hex_contract_address = self.__sdk.neo_vm.claim_record( ).hex_contract_address merkle_proof = self.__sdk.get_network().get_merkle_proof(tx_hash) current_block_height = merkle_proof['CurBlockHeight'] target_hash = merkle_proof['TransactionsRoot'] merkle_root = merkle_proof['CurBlockRoot'] tx_block_height = self.__sdk.get_network().get_block_height_by_tx_hash( tx_hash) target_hash_list = merkle_proof['TargetHashes'] proof_node = MerkleVerifier.get_proof(tx_block_height, target_hash_list, current_block_height) result = MerkleVerifier.validate_proof(proof_node, target_hash, merkle_root) if not result: raise SDKException(ErrorCode.other_error('Invalid merkle proof')) self.__blk_proof = BlockchainProof(tx_hash, hex_contract_address, current_block_height, merkle_root, proof_node) return self.__blk_proof
def __init__(self, sdk): self.__sdk = sdk self.__head = None self.__payload = None self.__signature = b'' self.__blk_proof = BlockchainProof(sdk)
class Claim(object): def __init__(self, sdk): self.__sdk = sdk self.__head = None self.__payload = None self.__signature = b'' self.__blk_proof = BlockchainProof(sdk) def __iter__(self): data = dict(Header=dict(self.__head), Payload=dict(self.__payload), Signature=self.to_str_signature(), Proof=dict(self.__blk_proof)) for key, value in data.items(): yield (key, value) @property def claim_id(self): if not isinstance(self.__payload, Payload): return '' return self.__payload.jti @property def head(self): return self.__head @head.setter def head(self, kid: str): if not isinstance(kid, str): raise SDKException(ErrorCode.require_str_params) self.__head = Header(kid) @property def payload(self): return self.__payload @property def signature(self): return self.__signature @property def blk_proof(self): return self.__blk_proof @blk_proof.setter def blk_proof(self, blk_proof: dict): self.__blk_proof.proof = blk_proof def set_claim(self, kid: str, iss_ont_id: str, sub_ont_id: str, exp: int, context: str, clm: dict, clm_rev: dict, jti: str = '', ver: str = 'v1.0'): if not isinstance(jti, str): raise SDKException(ErrorCode.require_str_params) if jti == '': jti = Digest.sha256(uuid.uuid1().bytes, is_hex=True) self.__head = Header(kid) self.__payload = Payload(ver, iss_ont_id, sub_ont_id, int(time()), exp, context, clm, clm_rev, jti) def generate_signature(self, iss: Account, verify_kid: bool = True): if not isinstance(self.__head, Header) or not isinstance(self.__payload, Payload): raise SDKException(ErrorCode.other_error('Please set claim parameters first.')) if verify_kid: key_index = int(self.__head.kid.split('-')[1]) result = self.__sdk.native_vm.ont_id().verify_signature(iss.get_ont_id(), key_index, iss) if not result: raise SDKException(ErrorCode.other_error('Issuer account error.')) b64_head = self.__head.to_base64() b64_payload = self.__payload.to_base64() msg = f'{b64_head}.{b64_payload}'.encode('utf-8') self.__signature = iss.generate_signature(msg) return self.__signature def validate_signature(self, b64_claim: str): try: b64_head, b64_payload, b64_signature, _ = b64_claim.split('.') except ValueError: raise SDKException(ErrorCode.invalid_b64_claim_data) head = Header.from_base64(b64_head) payload = Payload.from_base64(b64_payload) signature = base64.b64decode(b64_signature) kid = head.kid iss_ont_id = payload.iss msg = f'{b64_head}.{b64_payload}'.encode('ascii') pk = '' pub_keys = self.__sdk.native_vm.ont_id().get_public_keys(iss_ont_id) if len(pub_keys) == 0: raise SDKException(ErrorCode.invalid_claim_head_params) for pk_info in pub_keys: if kid == pk_info.get('PubKeyId', ''): pk = pk_info.get('Value', '') break if pk == '': raise SDKException(ErrorCode.invalid_b64_claim_data) handler = SignatureHandler(head.alg) result = handler.verify_signature(pk, msg, signature) return result def to_bytes_signature(self): return self.__signature def to_str_signature(self): return self.__signature.decode('latin-1') def to_b64_signature(self): return base64.b64encode(self.to_bytes_signature()).decode('ascii') @staticmethod def from_base64_signature(b64_signature: str): return bytes.hex(base64.b64decode(b64_signature)) def generate_blk_proof(self, iss_acct: Account, payer: Account, gas_limit: int, gas_price: int, is_big_endian: bool = True, hex_contract_address: str = ''): if not isinstance(hex_contract_address, str): raise SDKException(ErrorCode.require_str_params) if len(hex_contract_address) != 0 and len(hex_contract_address) == 40: self.__sdk.neo_vm.claim_record().hex_contract_address = hex_contract_address tx_hash = self.__sdk.neo_vm.claim_record().commit(self.payload.jti, iss_acct, self.payload.sub, payer, gas_limit, gas_price) sleep(12) hex_contract_address = self.__sdk.neo_vm.claim_record().hex_contract_address merkle_proof = self.__sdk.get_network().get_merkle_proof(tx_hash) tx_block_height = merkle_proof['BlockHeight'] current_block_height = merkle_proof['CurBlockHeight'] target_hash = merkle_proof['TransactionsRoot'] merkle_root = merkle_proof['CurBlockRoot'] target_hash_list = merkle_proof['TargetHashes'] proof_node = MerkleVerifier.get_proof(tx_block_height, target_hash_list, current_block_height) result = MerkleVerifier.validate_proof(proof_node, target_hash, merkle_root, is_big_endian) if not result: raise SDKException(ErrorCode.other_error('Invalid merkle proof')) self.__blk_proof.set_proof(tx_hash, hex_contract_address, tx_block_height, merkle_root, proof_node) return self.__blk_proof def validate_blk_proof(self, is_big_endian: bool = True): return self.__blk_proof.validate_blk_proof(is_big_endian) def to_base64(self): b64_head = self.__head.to_base64() b64_payload = self.__payload.to_base64() b64_signature = self.to_b64_signature() b64_blockchain_proof = self.__blk_proof.to_base64() return f'{b64_head}.{b64_payload}.{b64_signature}.{b64_blockchain_proof}' def from_base64(self, b64_claim: str, is_big_endian: bool = True): try: b64_head, b64_payload, b64_signature, b64_blk_proof = b64_claim.split('.') except ValueError: raise SDKException(ErrorCode.invalid_b64_claim_data) self.__head = Header.from_base64(b64_head) self.__payload = Payload.from_base64(b64_payload) self.__signature = base64.b64decode(b64_signature) self.__blk_proof = BlockchainProof(self.__sdk).from_base64(b64_blk_proof, is_big_endian)
def blockchain_proof(self): return BlockchainProof(self.__sdk)
def blockchain_proof(self): if self.__blockchain_proof is None: self.__blockchain_proof = BlockchainProof(self.__sdk) return self.__blockchain_proof