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)
Beispiel #2
0
    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
Beispiel #3
0
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
Beispiel #4
0
    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)
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
    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
Beispiel #8
0
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))
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #15
0
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
Beispiel #16
0
    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
Beispiel #17
0
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
Beispiel #22
0
    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
Beispiel #23
0
    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')
Beispiel #25
0
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)))