Config Transaction Family Specification


The config transaction family provides a methodology for storing on-chain configuration settings.

The settings stored in state as a result of this transaction family play a critical role in the operation of a validator. For example, the consensus module uses these settings; in the case of PoET, one cross-network setting is target wait time (which must be the same across validators), and this setting is stored as sawtooth.poet.target_wait_time. Other parts of the system use these settings similarly; for example, the list of enabled transaction families is used by the transaction processing platform.

In addition, pluggable components such as transaction family implementations can use the settings during their execution.

This design supports two authorization options: a) a single authorized key which can make changes, and b) multiple authorized keys. In the case of multiple keys, a percentage of votes signed by the keys is required to make a change.


While usable in a production sense, this transaction family also serves as a reference specification and implementation. The authorization scheme here provides a simple voting mechanism; another authorization scheme may be better in practice. Implementations which use a different authorization scheme can replace this implementation by adhering to the same addressing scheme and content format for settings. (For example, the location of PoET settings can not change, or the PoET consensus module will not be able to find them.)


This section describes in detail how config settings are stored and addressed using the config transaction family.

The configuration data consists of setting/value pairs. A setting is the name for the item of configuration data. The value is the data in the form of a string.


Settings are namespaced using dots:

Setting (Examples) Value
sawtooth.poet.target_wait_time 5
sawtooth.validator.max_transactions_per_block 1000

The config transaction family uses the following settings for its own configuration:

Setting (Config) Value Description List of public keys allowed to vote. Percentage of keys required for a proposal to be accepted. A list of proposals to make configuration changes (see note)

Note is a base64 encoded string of the protobuf message ConfigCandidates. This setting cannot be modified by a proposal or a vote.

Definition of Setting Entries

The following protocol buffers definition defines setting entries:

File: sawtooth-core/protos/setting.proto
// Setting Container for the resulting state
message Setting {
    // Contains a setting entry (or entries, in the case of collisions).
    message Entry {
        string key = 1;
        string value = 2;

    // List of setting entries - more than one implies a state key collision
    repeated Entry entries = 1;

The setting ‘’ is stored as defined by the following protocol buffers definition. The value returned by this setting is a base64 encoded ConfigCandidates message:

File: sawtooth-core/families/config/protos/config.proto
// Contains the vote counts for a given proposal.
message ConfigCandidate {
    // An individual vote record
    message VoteRecord {
        // The public key of the voter
        string public_key = 1;

        // The voter's actual vote
        ConfigVote.Vote vote = 2;


    // The proposal id, a hash of the original proposal
    string proposal_id = 1;

    // The active propsal
    ConfigProposal proposal = 2;

    // list of votes
    repeated VoteRecord votes = 3;

// Contains all the configuration candiates up for vote.
message ConfigCandidates {
    repeated ConfigCandidate candidates = 1;


When a setting is read or changed, it is accessed by addressing it using the following algorithm:

Setting keys are broken into four parts, based on the dots in the string. For example, the address for the key a.b.c is computed based on a, b, c and the empty string. A longer key, for example a.b.c.d.e, is still broken into four parts, but the remain pieces are in the last part: a, b, c and d.e.

Each of these pieces has a short hash computed (the first 16 characters of its SHA256 hash in hex) and is joined into a single address, with the config namespace (000000) added at the beginning.

For example, the setting could be set like this:

>>> '000000' + hashlib.sha256('sawtooth'.encode()).hexdigest()[:16] + \
    hashlib.sha256('config'.encode()).hexdigest()[:16] + \
    hashlib.sha256('vote'.encode()).hexdigest()[:16] + \

Transaction Payload

Config transaction family payloads are defined by the following protocol buffers code:

File: sawtooth-core/families/config/protos/config.proto
// Configuration Setting Payload
// - Contains either a proposal or a vote.
message ConfigPayload {
    // The action indicates data is contained within this payload
    enum Action {
        // A proposal action - data will be a ConfigProposal
        PROPOSE = 0;

        // A vote action - data will be a ConfigVote
        VOTE = 1;
    // The action of this payload
    Action action = 1;

    // The content of this payload
    bytes data = 2;

// Configuration Setting Proposal
// This message proposes a change in a setting value.
message ConfigProposal {
    // The setting key.  E.g. sawtooth.consensus.module
    string setting = 1;

    // The setting value. E.g. 'poet'
    string value = 2;

    // allow duplicate proposals with different hashes
    // randomly created by the client
    string nonce = 3;

// Configuration Setting Vote
// In ballot mode, a propsal must be voted on.  This message indicates an
// acceptance or rejection of a proposal, where the proposal is identified
// by its id.
message ConfigVote {
    enum Vote {
        ACCEPT = 0;
        REJECT = 1;

    // The id of the proposal, as found in the
    // setting field
    string proposal_id = 1;

    Vote vote = 2;

Transaction Header

Inputs and Outputs

The inputs for config family transactions must include:

  • the address of
  • the address of
  • the address of
  • the address of the setting being changed

The outputs for config family transactions must include:

  • the address of
  • the address of the setting being changed




  • family_name: “sawtooth_config”
  • family_version: “1.0”


The encoding field must be set to “application/protobuf”.


Initially, the transaction processor gets the current values of from the state.

The public key of the transaction signer is checked against the values in the list of authorized keys. If it is empty, all public keys are allowed.

A Propose action is validated. If it fails, it is considered an invalid transaction. A proposal_id is calculated by taking the sha256 hash of the raw ConfigProposal bytes as they exist in the payload. Duplicate proposal_ids causes an invalid transaction. The proposal will be recorded in the ConfigProposals stored in, with one “accept” vote counted. The transaction processor outputs a DEBUG-level logging message similar to

"Adding proposal {}: {}".format(proposal_id, repr(proposal_data).

A Vote action is validated, checking to see if proposal_id exists, and the public key of the transaction has not already voted. The value of is read from the state. If the “accept” vote count is equal to or above the approval threshold, the proposal is applied to the state. This results in the above INFO message being logged. The proposal is deleted from the ConfigProposals record.

If the “reject” vote count is equal to or above the approval threshold, then it is deleted from and an appropriate debug logging message logged.

Otherwise, the vote is recorded in the list of by the public key and vote pair.

Validation of configuration settings is as follows:

  • must be a positive integer and must be between 1 and the number of authorized keys, inclusive
  • may not be set by a proposal