def assertValidTransactionHeader(self, header, signature, payload, signer_public_key): """Check a transaction header is valid given a payload""" if isinstance(header, bytes): decoded = transaction_pb2.TransactionHeader() decoded.ParseFromString(header) header = decoded self.assertIsInstance(header, transaction_pb2.TransactionHeader) self.assertEqual(header.family_name, addresser.family.name) self.assertEqual(header.family_version, addresser.family.version) self.assertIsInstance(header.nonce, str) self.assertEqual(len(header.nonce), 32) self.assertEqual(header.signer_public_key, signer_public_key) self.assertEqual(header.payload_sha512, sha512(payload.SerializeToString()).hexdigest()) signer = Key(public_key=signer_public_key) self.assertTrue( signer.verify(signature=signature, message=header.SerializeToString())) other_key = Key() self.assertFalse( other_key.verify(signature=signature, message=header.SerializeToString())) self.assertEqual(header.inputs, payload.inputs) self.assertEqual(header.outputs, payload.outputs)
def _transaction_header(txn_key, batch_key, inputs, outputs, payload): txn_header_bytes = transaction_pb2.TransactionHeader( family_name=helper.TP_FAMILYNAME, family_version=helper.TP_VERSION, inputs=inputs, outputs=outputs, signer_public_key=txn_key.get_public_key().as_hex( ), # signer.get_public_key().as_hex(), # In this example, we're signing the batch with the same private key, # but the batch can be signed by another party, in which case, the # public key will need to be associated with that key. batcher_public_key=batch_key.get_public_key().as_hex( ), # signer.get_public_key().as_hex(), # In this example, there are no dependencies. This list should include # an previous transaction header signatures that must be applied for # this transaction to successfully commit. # For example, # dependencies=['540a6803971d1880ec73a96cb97815a95d374cbad5d865925e5aa0432fcf1931539afe10310c122c5eaae15df61236079abbf4f258889359c4d175516934484a'], dependencies=[], nonce=random.random().hex().encode(), payload_sha512=hashlib.sha512( payload.SerializeToString()).hexdigest()).SerializeToString() signature = txn_key.sign(txn_header_bytes) return txn_header_bytes, signature
def create_bgt_transaction(verb, name, value, signer): payload = BgtPayload( verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. addr = make_bgt_address(name) header = transaction_pb2.TransactionHeader( signer_public_key=signer.get_public_key().as_hex(), family_name='bgt', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_sha512=payload.sha512(), batcher_public_key=signer.get_public_key().as_hex(), nonce=hex(random.randint(0, 2**64))) header_bytes = header.SerializeToString() signature = signer.sign(header_bytes) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def _assert_validator_transaction(self, public_key, target_file): filename = os.path.join(self._temp_dir, target_file) batch_list = batch_pb.BatchList() with open(filename, 'rb') as batch_file: batch_list.ParseFromString(batch_file.read()) self.assertEqual(1, len(batch_list.batches)) batch = batch_list.batches[0] self.assertEqual(1, len(batch.transactions)) batch_header = batch_pb.BatchHeader() batch_header.ParseFromString(batch.header) self.assertEqual(public_key, batch_header.signer_public_key) txn = batch.transactions[0] txn_header = txn_pb.TransactionHeader() txn_header.ParseFromString(txn.header) self.assertEqual(public_key, txn_header.signer_public_key) self.assertEqual('sawtooth_validator_registry', txn_header.family_name) payload = vr_pb.ValidatorRegistryPayload() payload.ParseFromString(txn.payload) self._assert_key_state(payload.signup_info.poet_public_key)
def create_intkey_transaction(verb, name, value, private_key, public_key): payload = IntKeyPayload( verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. addr = make_intkey_address(name) header = transaction_pb2.TransactionHeader( signer_public_key=public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_sha512=payload.sha512(), batcher_public_key=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def create_intkey_transaction(verb, name, value, private_key, public_key): payload = IntKeyPayload(verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. intkey_prefix = hashlib.sha512('intkey'.encode('utf-8')).hexdigest()[0:6] addr = intkey_prefix + hashlib.sha512(name.encode('utf-8')).hexdigest() header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=[], payload_encoding="application/cbor", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = bitcoin.ecdsa_sign(header_bytes, private_key) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def _make_batch(self, payload, inputs, outputs, signer): """Creates and signs a batch. """ signer_public_key = signer.get_public_key().as_hex() payload_bytes = payload.SerializeToString() txn_header = transaction_pb2.TransactionHeader( family_name=self._family_name, family_version=self._family_version, inputs=inputs, outputs=outputs, signer_public_key=signer_public_key, batcher_public_key=signer_public_key, payload_sha512=hashlib.sha512(payload_bytes).hexdigest()) txn_header_bytes = txn_header.SerializeToString() txn = transaction_pb2.Transaction( header=txn_header_bytes, header_signature=signer.sign(txn_header_bytes), payload=payload_bytes) batch_header = batch_pb2.BatchHeader( signer_public_key=signer_public_key, transaction_ids=[txn.header_signature]) batch_header_bytes = batch_header.SerializeToString() batch = batch_pb2.Batch( header=batch_header_bytes, header_signature=signer.sign(batch_header_bytes), transactions=[txn]) return batch
def unmake_item(batch_object, signer_public_key=None, batcher_public_key=BATCHER_KEY_PAIR.public_key): """Will unmake_item a transaction or payload, and return a message. Validation of signatures will occur if public keys are provided. Only used for testing purposes. """ if isinstance(batch_object, transaction_pb2.Transaction): header = transaction_pb2.TransactionHeader() header.ParseFromString(batch_object.header) assert header.payload_sha512 == sha512( batch_object.payload).hexdigest() if signer_public_key: assert header.signer_public_key == signer_public_key signer = Key(public_key=signer_public_key) signer.verify(signature=batch_object.header_signature, message=batch_object.header) payload = RBACPayload() payload.ParseFromString(batch_object.payload) batch_object = payload if isinstance(batch_object, RBACPayload): _, message, _, _ = unmake_payload(payload=batch_object) return message raise Exception("unmake doesn't handle type {}\n{}".format( type(batch_object), batch_object))
def create_intkey_transaction(verb, name, value, deps, signer): payload = IntKeyPayload(verb=verb, name=name, value=value) addr = make_intkey_address(name) header = transaction_pb2.TransactionHeader( signer_public_key=signer.get_public_key().as_hex(), family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=deps, payload_sha512=payload.sha512(), batcher_public_key=signer.get_public_key().as_hex(), nonce=hex(random.randint(0, 2**64))) header_bytes = header.SerializeToString() signature = signer.sign(header_bytes) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def make_ping(): """ Makes a ping transaction (a transaction that does nothing but make sure the validator and transaction processor is up and responding) """ payload = "ping".encode("utf-8") header = transaction_pb2.TransactionHeader( inputs=[], outputs=[], batcher_public_key=BATCHER_KEY_PAIR.public_key, dependencies=[], family_name=addresser.family.name, family_version=addresser.family.version, nonce=uuid4().hex, signer_public_key=BATCHER_KEY_PAIR.public_key, payload_sha512=sha512(payload).hexdigest(), ) transaction = transaction_pb2.Transaction( payload=payload, header=header.SerializeToString(), header_signature=BATCHER_KEY_PAIR.sign(header.SerializeToString()), ) batch = make_batch(transaction=transaction, batcher_keypair=BATCHER_KEY_PAIR) batch_list = batch_to_list(batch=batch) batch_request = make_batch_request(batch_list=batch_list) return transaction, batch, batch_list, batch_request
def make_header(inputs, outputs, payload_sha512, signer_pubkey, batcher_pubkey): header = transaction_pb2.TransactionHeader( inputs=inputs, outputs=outputs, batcher_public_key=batcher_pubkey, dependencies=[], family_name=addresser.family.name, family_version=addresser.family.version, nonce=uuid4().hex, signer_public_key=signer_pubkey, payload_sha512=payload_sha512, ) return header
def create_jvm_sc_transaction(verb, private_key, public_key, bytecode=None, methods=None, byte_addr=None, method=None, parameters=None, addresses=None): payload = JVM_SC_Payload(verb=verb, bytecode=bytecode, methods=methods, byte_addr=byte_addr, method=method, parameters=parameters) if addresses is None: addresses = [] # The prefix should eventually be looked up from the # validator's namespace registry. if byte_addr is not None: addr = byte_addr elif bytecode is not None: addr = get_address('jvm_sc', bytecode) else: raise Exception addresses.append(addr) header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='jvm_sc', family_version='1.0', inputs=addresses, outputs=addresses, dependencies=[], payload_encoding="application/protobuf", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=str(time.time())) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.payload_bytes, header_signature=signature) return transaction
def create_intkey_transaction(verb, name, value, deps, private_key, public_key): """Creates a signed intkey transaction. Args: verb (str): the action the transaction takes, either 'set', 'inc', or 'dec' name (str): the variable name which is altered by verb and value value (int): the amount to set, increment, or decrement deps ([str]): a list of transaction header_signatures which are required dependencies which must be processed prior to processing this transaction private_key (str): the private key used to sign the transaction public_key (str): the public key associated with the private key - the public key is included in the transaction as signer_pubkey Returns: transaction (transaction_pb2.Transaction): the signed intkey transaction """ payload = IntKeyPayload(verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. intkey_prefix = hashlib.sha512('intkey'.encode('utf-8')).hexdigest()[0:6] addr = intkey_prefix + hashlib.sha512(name.encode('utf-8')).hexdigest() header = transaction_pb2.TransactionHeader( signer_pubkey=public_key, family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=deps, payload_encoding="application/cbor", payload_sha512=payload.sha512(), batcher_pubkey=public_key, nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signing.sign(header_bytes, private_key) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def create_intkey_transaction(verb, name, value, deps, signer): """Creates a signed intkey transaction. Args: verb (str): the action the transaction takes, either 'set', 'inc', or 'dec' name (str): the variable name which is altered by verb and value value (int): the amount to set, increment, or decrement deps ([str]): a list of transaction header_signatures which are required dependencies which must be processed prior to processing this transaction signer (:obj:`Signer`): the cryptographic signer for signing the transaction Returns: transaction (transaction_pb2.Transaction): the signed intkey transaction """ payload = IntKeyPayload( verb=verb, name=name, value=value) # The prefix should eventually be looked up from the # validator's namespace registry. addr = make_intkey_address(name) header = transaction_pb2.TransactionHeader( signer_public_key=signer.get_public_key().as_hex(), family_name='intkey', family_version='1.0', inputs=[addr], outputs=[addr], dependencies=deps, payload_sha512=payload.sha512(), batcher_public_key=signer.get_public_key().as_hex(), nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signer.sign(header_bytes) transaction = transaction_pb2.Transaction( header=header_bytes, payload=payload.to_cbor(), header_signature=signature) return transaction
def make_transaction_header(payload, signer_keypair): """ Make the signed transaction header for a payload """ header = transaction_pb2.TransactionHeader( inputs=payload.inputs, outputs=payload.outputs, batcher_public_key=signer_keypair.public_key, dependencies=[], family_name=addresser.family.name, family_version=addresser.family.version, nonce=uuid4().hex, signer_public_key=signer_keypair.public_key, payload_sha512=sha512(payload.SerializeToString()).hexdigest(), ) signature = signer_keypair.sign(header.SerializeToString()) return header, signature
def _create_proposal(self, block_header, pbft_enclave_module): """ proposal request """ public_key_hash = hashlib.sha256(block_header.signer_public_key.encode()).hexdigest() nonce = SignupInfo.block_id_to_nonce(block_header.previous_block_id) setting = 'sawtooth.consensus.pbft.max_log_size' if False: # try to set pbft params proposal = SettingProposal( setting=setting, value='1003', nonce=nonce) payload = SettingsPayload(data=proposal.SerializeToString(),action=SettingsPayload.PROPOSE) serialized = payload.SerializeToString() input_addresses = _config_inputs(setting) output_addresses = _config_outputs(setting) header = txn_pb.TransactionHeader( signer_public_key=block_header.signer_public_key, family_name='sawtooth_settings', family_version='1.0', inputs=input_addresses, outputs=output_addresses, dependencies=[], payload_sha512=hashlib.sha512(serialized).hexdigest(), batcher_public_key=block_header.signer_public_key, nonce=hex(random.randint(0, 2**64))).SerializeToString() signature = self._batch_publisher.identity_signer.sign(header) transaction = txn_pb.Transaction( header=header, payload=serialized, header_signature=signature) LOGGER.info('payload action=%s nonce=%s', payload.action, nonce) self._batch_publisher.send([transaction]) else: # get setting pass
def make_header(inputs, outputs, payload_sha512, signer_pubkey, batcher_pubkey, dependencies): if dependencies: dependencies = [dependencies] else: dependencies = [] header = transaction_pb2.TransactionHeader( inputs=inputs, outputs=outputs, batcher_public_key=batcher_pubkey, dependencies=dependencies, family_name=addresser.FAMILY_NAME, family_version='1.0', nonce=uuid4().hex, signer_public_key=signer_pubkey, payload_sha512=payload_sha512) return header
def assertValidTransactionHeader( self, header, signature, message, message_type, inputs, outputs, signer_public_key, ): if isinstance(header, bytes): decoded = transaction_pb2.TransactionHeader() decoded.ParseFromString(header) header = decoded payload = self.make_payload(message=message, message_type=message_type) self.assertIsInstance(header, transaction_pb2.TransactionHeader) self.assertEqual(header.family_name, addresser.FAMILY_NAME) self.assertEqual(header.family_version, addresser.FAMILY_VERSION) self.assertIsInstance(header.nonce, str) self.assertEqual(len(header.nonce), 32) self.assertEqual(header.signer_public_key, signer_public_key) self.assertEqual( header.payload_sha512, sha512(payload.SerializeToString()).hexdigest() ) signer = Key(public_key=signer_public_key) self.assertTrue( signer.verify(signature=signature, message=header.SerializeToString()) ) other_key = Key() self.assertFalse( other_key.verify(signature=signature, message=header.SerializeToString()) ) self.assertEqual(header.inputs, inputs) self.assertEqual(header.outputs, outputs) self.assertValidInputs( inputs=header.inputs, outputs=header.outputs, message_type=message_type, message=message, )
def make_transaction_header( self, payload, signer_keypair, batcher_public_key=BATCHER_KEY_PAIR.public_key): """Make the signed transaction header for a payload""" header = transaction_pb2.TransactionHeader( inputs=payload.inputs, outputs=payload.outputs, batcher_public_key=batcher_public_key, dependencies=[], family_name=addresser.FAMILY_NAME, family_version=addresser.FAMILY_VERSION, nonce=uuid4().hex, signer_public_key=signer_keypair.public_key, payload_sha512=sha512(payload.SerializeToString()).hexdigest(), ) signature = signer_keypair.sign(header.SerializeToString()) return header, signature
def create_transaction(payload, addr, signer): header = transaction_pb2.TransactionHeader( signer_public_key=signer.get_public_key().as_hex(), family_name=get_family_name(), family_version=get_family_version(), inputs=[addr], outputs=[addr], dependencies=[], payload_sha512=payload.sha512(), batcher_public_key=signer.get_public_key().as_hex(), nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signer.sign(header_bytes) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.get_encrypted(), header_signature=signature) return transaction
def create_noop_transaction(signer): payload = NoopPayload() header = transaction_pb2.TransactionHeader( signer_public_key=signer.get_public_key().as_hex(), family_name='noop', family_version='1.0', inputs=[], outputs=[], dependencies=[], payload_sha512=payload.sha512(), batcher_public_key=signer.get_public_key().as_hex(), nonce=time.time().hex().encode()) header_bytes = header.SerializeToString() signature = signer.sign(header_bytes) transaction = transaction_pb2.Transaction(header=header_bytes, payload=payload.nonce, header_signature=signature) return transaction
def _register_signup_information(self, block_header, poet_enclave_module): # Create signup information for this validator, putting the block ID # of the block previous to the block referenced by block_header in the # nonce. Block ID is better than wait certificate ID for testing # freshness as we need to account for non-PoET blocks. public_key_hash = \ hashlib.sha256( block_header.signer_public_key.encode()).hexdigest() nonce = SignupInfo.block_id_to_nonce(block_header.previous_block_id) signup_info = \ SignupInfo.create_signup_info( poet_enclave_module=poet_enclave_module, originator_public_key_hash=public_key_hash, nonce=nonce) # Create the validator registry payload payload = \ vr_pb.ValidatorRegistryPayload( verb='register', name='validator-{}'.format(block_header.signer_public_key[:8]), id=block_header.signer_public_key, signup_info=vr_pb.SignUpInfo( poet_public_key=signup_info.poet_public_key, proof_data=signup_info.proof_data, anti_sybil_id=signup_info.anti_sybil_id, nonce=nonce), ) serialized = payload.SerializeToString() # Create the address that will be used to look up this validator # registry transaction. Seems like a potential for refactoring.. validator_entry_address = \ PoetBlockPublisher._validator_registry_namespace + \ hashlib.sha256(block_header.signer_public_key.encode()).hexdigest() # Create a transaction header and transaction for the validator # registry update amd then hand it off to the batch publisher to # send out. output_addresses = \ [validator_entry_address, PoetBlockPublisher._validator_map_address] input_addresses = \ output_addresses + \ [SettingsView.setting_address( 'sawtooth.poet.report_public_key_pem'), SettingsView.setting_address( 'sawtooth.poet.valid_enclave_measurements'), SettingsView.setting_address( 'sawtooth.poet.valid_enclave_basenames')] header = \ txn_pb.TransactionHeader( signer_public_key=block_header.signer_public_key, family_name='sawtooth_validator_registry', family_version='1.0', inputs=input_addresses, outputs=output_addresses, dependencies=[], payload_sha512=hashlib.sha512(serialized).hexdigest(), batcher_public_key=block_header.signer_public_key, nonce=time.time().hex().encode()).SerializeToString() signature = self._batch_publisher.identity_signer.sign(header) transaction = \ txn_pb.Transaction( header=header, payload=serialized, header_signature=signature) LOGGER.info( 'Register Validator Name=%s, ID=%s...%s, PoET public key=%s...%s, ' 'Nonce=%s', payload.name, payload.id[:8], payload.id[-8:], payload.signup_info.poet_public_key[:8], payload.signup_info.poet_public_key[-8:], nonce) self._batch_publisher.send([transaction]) # Store the key state so that we can look it up later if need be and # set the new key as our active key LOGGER.info('Save key state PPK=%s...%s => SSD=%s...%s', signup_info.poet_public_key[:8], signup_info.poet_public_key[-8:], signup_info.sealed_signup_data[:8], signup_info.sealed_signup_data[-8:]) self._poet_key_state_store[signup_info.poet_public_key] = \ PoetKeyState( sealed_signup_data=signup_info.sealed_signup_data, has_been_refreshed=False, signup_nonce=nonce) self._poet_key_state_store.active_key = signup_info.poet_public_key
def create_user_transaction(self, name, username, metadata): txn_private_key = Secp256k1PrivateKey.new_random() batch_private_key = Secp256k1PrivateKey.new_random() txn_key = Key(txn_private_key.as_hex()) batch_key = Key(batch_private_key.as_hex()) batchlist, sig = create_user( txn_key, batch_key, name, username, txn_key.public_key, metadata ) self.assertEqual(type(sig), str) self.assertEqual(type(batchlist), batch_pb2.BatchList) self.assertEqual(len(sig), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(sig)) batch_count = 0 for batch in batchlist.batches: batch_count += 1 self.assertEqual(type(batch), batch_pb2.Batch) self.assertEqual(type(batch.header_signature), str) self.assertEqual(len(batch.header_signature), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(batch.header_signature)) trans_count = 0 for transaction in batch.transactions: trans_count += 1 self.assertEqual(type(transaction.header), bytes) self.assertEqual(type(transaction.header_signature), str) self.assertEqual(type(transaction.payload), bytes) self.assertEqual(len(transaction.header_signature), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(transaction.header_signature)) header = transaction_pb2.TransactionHeader() header.ParseFromString(transaction.header) self.assertEqual(type(header), transaction_pb2.TransactionHeader) self.assertEqual(header.family_name, addresser.FAMILY_NAME) self.assertEqual(header.family_version, addresser.FAMILY_VERSION) self.assertEqual(header.batcher_public_key, batch_key.public_key) self.assertEqual(header.signer_public_key, txn_key.public_key) self.assertEqual(len(header.payload_sha512), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(header.payload_sha512)) input_count = 0 for address in header.inputs: input_count += 1 self.assertEqual(type(address), str) self.assertEqual(len(address), addresser.ADDRESS_LENGTH) self.assertEqual( addresser.address_is(address), addresser.AddressSpace.USER ) self.assertEqual(input_count, 1) output_count = 0 for address in header.outputs: output_count += 1 self.assertEqual(type(address), str) self.assertEqual(len(address), addresser.ADDRESS_LENGTH) self.assertEqual( addresser.address_is(address), addresser.AddressSpace.USER ) self.assertEqual(output_count, 1) payload = rbac_payload_pb2.RBACPayload() payload.ParseFromString(transaction.payload) self.assertEqual(type(payload), rbac_payload_pb2.RBACPayload) self.assertEqual( payload.message_type, rbac_payload_pb2.RBACPayload.CREATE_USER ) self.assertEqual(type(payload.content), bytes) user = user_transaction_pb2.CreateUser() user.ParseFromString(payload.content) self.assertEqual(type(user), user_transaction_pb2.CreateUser) self.assertEqual(user.name, name) self.assertEqual(user.user_name, username) self.assertEqual(type(user.user_id), str) self.assertEqual(user.user_id, txn_key.public_key) self.assertEqual(trans_count, 1) self.assertEqual(batch_count, 1)
def _register_signup_information(self, block_header, pbft_enclave_module=None): # Create signup information for this validator, putting the block ID # of the block previous to the block referenced by block_header in the # nonce. Block ID is better than wait certificate ID for testing # freshness as we need to account for non-BGT blocks. LOGGER.debug('_register_signup_information: TRY to REGISTER') public_key_hash = hashlib.sha256( block_header.signer_public_key.encode()).hexdigest() nonce = SignupInfo.block_id_to_nonce(block_header.previous_block_id) pbft_public_key = self._validator_id anti_sybil_id = hashlib.sha256(pbft_public_key.encode()).hexdigest() signup_data = { 'pbft_public_key': pbft_public_key, } sealed_signup_data = base64.b64encode( dict2json(signup_data).encode()).decode('utf-8') """ signup_info = SignupInfo.create_signup_info( pbft_enclave_module=pbft_enclave_module, originator_public_key_hash=public_key_hash, nonce=nonce) """ # Create the validator registry payload payload = vr_pb.BgxValidatorRegistryPayload( verb='register', name='validator-{}'.format(block_header.signer_public_key[:8]), id=block_header.signer_public_key, node=self._node, signup_info=vr_pb.BgxSignUpInfo( pbft_public_key=pbft_public_key, # signup_info.pbft_public_key, anti_sybil_id=anti_sybil_id, # signup_info.anti_sybil_id, nonce=nonce), ) serialized = payload.SerializeToString() # Create the address that will be used to look up this validator # registry transaction. Seems like a potential for refactoring.. validator_entry_address = PbftBlockPublisher._validator_registry_namespace + hashlib.sha256( block_header.signer_public_key.encode()).hexdigest() # Create a transaction header and transaction for the validator # registry update amd then hand it off to the batch publisher to # send out. output_addresses = [ validator_entry_address, PbftBlockPublisher._validator_map_address ] input_addresses = output_addresses + \ [SettingsView.setting_address('sawtooth.bgt.report_public_key_pem'), SettingsView.setting_address('sawtooth.bgt.valid_enclave_measurements'), SettingsView.setting_address('sawtooth.bgt.valid_enclave_basenames') ] header = txn_pb.TransactionHeader( signer_public_key=block_header.signer_public_key, family_name='bgx_validator_registry', family_version='1.0', inputs=input_addresses, outputs=output_addresses, dependencies=[], payload_sha512=hashlib.sha512(serialized).hexdigest(), batcher_public_key=block_header.signer_public_key, nonce=hex(random.randint(0, 2**64))).SerializeToString() signature = self._batch_publisher.identity_signer.sign(header) transaction = txn_pb.Transaction(header=header, payload=serialized, header_signature=signature) LOGGER.info('Register Validator Name=%s, ID=%s...%s,Nonce=%s', payload.name, payload.id[:8], payload.id[-8:], nonce) self._batch_publisher.send([transaction]) # Store the key state so that we can look it up later if need be and # set the new key as our active key self._pbft_key_state_store[pbft_public_key] = PbftKeyState( sealed_signup_data=sealed_signup_data, has_been_refreshed=False, signup_nonce=nonce) self._pbft_key_state_store.active_key = pbft_public_key LOGGER.debug('_register_signup_information: REGISTER DONE')
def do_create(args): """Executes the `poet registration` subcommand. This command generates a validator registry transaction and saves it to a file, whose location is determined by the args. The signup data, generated by the selected enclave, is also stored in a well-known location. """ signer = _read_signer(args.key) public_key = signer.get_public_key().as_hex() public_key_hash = sha256(public_key.encode()).hexdigest() nonce = SignupInfo.block_id_to_nonce(args.block) with PoetEnclaveModuleWrapper( enclave_module=args.enclave_module, config_dir=config.get_config_dir(), data_dir=config.get_data_dir()) as poet_enclave_module: signup_info = SignupInfo.create_signup_info( poet_enclave_module=poet_enclave_module, originator_public_key_hash=public_key_hash, nonce=nonce) print('Writing key state for PoET public key: {}...{}'.format( signup_info.poet_public_key[:8], signup_info.poet_public_key[-8:])) # Store the newly-created PoET key state, associating it with its # corresponding public key poet_key_state_store = \ PoetKeyStateStore( data_dir=config.get_data_dir(), validator_id=public_key) poet_key_state_store[signup_info.poet_public_key] = \ PoetKeyState( sealed_signup_data=signup_info.sealed_signup_data, has_been_refreshed=False, signup_nonce=nonce) # Create the validator registry payload payload = \ vr_pb.ValidatorRegistryPayload( verb='register', name='validator-{}'.format(public_key[:8]), id=public_key, signup_info=vr_pb.SignUpInfo( poet_public_key=signup_info.poet_public_key, proof_data=signup_info.proof_data, anti_sybil_id=signup_info.anti_sybil_id, nonce=SignupInfo.block_id_to_nonce(args.block))) serialized = payload.SerializeToString() # Create the address that will be used to look up this validator # registry transaction. Seems like a potential for refactoring.. validator_entry_address = \ VR_NAMESPACE + sha256(public_key.encode()).hexdigest() # Create a transaction header and transaction for the validator # registry update amd then hand it off to the batch publisher to # send out. output_addresses = [validator_entry_address, VALIDATOR_MAP_ADDRESS] input_addresses = \ output_addresses + \ [SettingsView.setting_address('sawtooth.poet.report_public_key_pem'), SettingsView.setting_address('sawtooth.poet.' 'valid_enclave_measurements'), SettingsView.setting_address('sawtooth.poet.valid_enclave_basenames')] header = \ txn_pb.TransactionHeader( signer_public_key=public_key, family_name='sawtooth_validator_registry', family_version='1.0', inputs=input_addresses, outputs=output_addresses, dependencies=[], payload_sha512=sha512(serialized).hexdigest(), batcher_public_key=public_key, nonce=time.time().hex().encode()).SerializeToString() signature = signer.sign(header) transaction = \ txn_pb.Transaction( header=header, payload=serialized, header_signature=signature) batch = _create_batch(signer, [transaction]) batch_list = batch_pb.BatchList(batches=[batch]) try: print('Generating {}'.format(args.output)) with open(args.output, 'wb') as batch_file: batch_file.write(batch_list.SerializeToString()) except IOError as e: raise CliException('Unable to write to batch file: {}'.format(str(e)))