SDBS #21 | StealthNode Extensible Attributes: A major protocol addition

Stealth
stealthsend
Published in
7 min readAug 26, 2019

Extensible Attributes are operator-defined blockchain data for StealthNodes

In today’s SDBS post I describe the addition of extensible attributes to StealthNodes, which are the validators of the qPoS blockchain protocol (also called “stakers”). An extensible attribute is a key-value pairing. Several examples of key-value pairings explain the simple concept:

  • “last_name” : “Doe”
  • “first_name” : “Jane”
  • “favorite_number” : 317
  • “certified_node” : “stealthnode.example.com”

In the first example, “last_name” is the key and “Doe” is the value of the key-value pairing. Note that double quotes are not part of the keys or values, but simply indicate that they are strings, as opposed to numbers (e.g. 317). Also, key-value pairings are often described using a colon (“:”) to separate a key from its value. This colon is part of neither the key nor value, and, like the double quotes above, is present as a matter of convention.

Extensible attributes are said to be “assigned” to StealthNodes in that properly authorized StealthNode operators (owners, delegates, or controllers) assign extensible attributes to StealthNodes. These assignments are recorded as Stealth blockchain transactions. As properties of StealthNodes, the state of all extensible attributes are also part of the staker registry, and as such are stored in RAM, meaning extensible attributes can be accessed quickly during runtime.

The purpose of extensible attributes is so that StealthNodes may voluntarily assume new attributes that can be used in the Stealth qPoS protocol without extensive code changes. Such extensive changes are avoided because all the mechanisms for the management of extensible attributes are built into the protocol. Extensible attributes can also be used with third party services, should individual StealthNode operators support these services by assigning the relevant attributes.

— — — — — — —

Example Use Case of Extensible Info

To understand extensible attributes and their intended uses, I give the example of Stealth certified nodes, discussed in SDBS #20. Briefly, each StealthNode may certify a single network address to which other nodes of the network know to preferentially retain a connection. Certified nodes are registered in the Stealth blockchain using extensible information, meaning a StealthNode operator or delegate will sign a transaction that specifies:

  1. The name of the StealthNode certifying the address
  2. The name of the extensible attribute, in this case “certified_node”
  3. The address to be certified

The addition of certified nodes to the qPoS protocol required a new attribute for StealthNodes, the key for which I designated “certified_node”. Other network nodes can use the “certified_node” attribute by:

  1. Cycling over every extant StealthNode
  2. Determining if a given StealthNode has the attribute keyed by “certified_node”
  3. Noting the address if so
  4. Preferentially retaining connections to this address (if valid) through minor adjustments to the network remodeling protocol

In the example of certified nodes, note that any StealthNode may voluntarily assume the “certified_node” attribute, but may also forego making such assignment, without any incentive or penalty.

— — — — — — —

Rationale for Extensible Attributes

While the “certified_node” attribute could have been hardcoded for every StealthNode as part of the reference client core, I decided to make a generalized system to create new StealthNode attributes to handle the extensive code changes for each new attribute once and for all. For an idea of what changes would be required for any single new hardcoded attribute, consider that a new attribute needs code for (1) a new opcode, (2) a new transaction type, (3) RPC command, (4) transaction creation validation, (4) block validation, (5) mempool validation, (6) a data field in StealthNode data structures, (7) accessors in the StealthNode code, (8) accessors in the registry code, (9) serialization and deserialization, (10) registry state changes, (11) representation code for various RPC informational commands, and other minor changes throughout the codebase. In short, adding a single hardcoded attribute would be two weeks of work for a single person, at the bare minimum.

A much better strategy would be to create a system to add attributes with very simple code changes, such that a new attribute could be introduced with only a few hours or even a few minutes of work. To this end, I created StealthNode extensible attributes.

— — — — — — —

When are Extensible Attributes Appropriate?

One question that may arise upon adding new features to StealthNodes is whether it is better to use an extensible attribute or simply put in the work to add a hardcoded attribute. In theory, the benefits of using extensible attributes are that they (1) reduce the coding time by at least an order of magnitude, (2) reduce new lines of code by at least an order of magnitude, and that they (3) are amenable to self-documenting code. The only real negative consequences are that accessing an extensible attribute value (1) may require conversion from a string to some other data type, and (2) requires lookup in a map data structure as opposed to referencing a memory offset, the former being somewhat slower. In practice, it may very well be up to the coder to decide which makes more sense based on intuition or taste. Personally, I would use a hardcoded attribute for any new features that have bearing on blockchain consensus, and extensible attributes for everything else, but at the moment this is simply a matter of preference.

— — — — — — —

Extensible Attribute Key-Value Constraints

Extensible attribute keys and values are constrained for a few reasons:

  • Keys and values should be short
  • Keys and values should consist of only printable characters (no tabs, escape sequences, etc)
  • Keys and values should not be able to form executable code for common programming languages

The reasoning behind this latter consideration is that we expect various third party services, like block explorers or StealthNode monitors, to attempt to render keys and values using languages like PHP and Javascript. Often, web developers do not have the same sensitivity to security as blockchain developers, and may have code that unintentionally executes the source for page content, such as keys and values of extensible attributes.

A dramatic example of this type of oversight was seen with the Steem blockchain, where over 250 accounts were hacked using this type of attack, including the accounts of the founders themselves. Notably, the attack occurred through the website hosted by the founder organization (Steemit).

With the above considerations in mind, the preliminary constraints for keys are:

  • Keys should be 16 bytes or fewer
  • Keys should consist only of lowercase letters and underscore

At the moment, constraints for values are that they should be 40 bytes or shorter and should contain only the characters a-z, A-Z, 0–9 and any of “._<>/@#,+-” (excluding the double quotes) and space. The exclusion of parentheses, curly brackets (“{“ and “}”), pipes (“|”), ampersands (“&”), semicolons (“:”), new lines, single quotes, and double quotes severely restrict the ability to express malicious code in every common language, while still allowing practically arbitrarily complex values.

These constraints give a keyspace of 80 billion trillion (8 * 10⁹ * 10¹²), and a value space of 650,000 trillion trillion (6.5 * 10⁵ * 10¹² * 10²). Meaning just about any reasonable key-value pairing is available, apart from perhaps the ability to use extensible attributes to store freeform data on the blockchain, which is explicitly not an intended use.

— — — — — — —

Permissioning

As part of extensible attributes, I created a permissioning system wherein different attributes could require different authorizations. As described in the whitepaper, StealthNodes have three different authorities, called “owner”, “delegate”, and “staker”. While owners can authorize any StealthNode state change, delegate and staker authorities do not necessarily overlap. The permissioning system of extensible attributes reflects this hierarchy. Thus, the potential combinations of authorities for a given extensible attribute are:

  • Owner (called QPKEY_OWNER in the codebase)
  • Owner or Delegate (QPKEY_OD)
  • Owner or Controller (QPKEY_OC)
  • Owner, Delegate, or Controller (QPKEY_ANY)

Permissions for new extensible attributes are specified in C++ in the file “meta.cpp”, where the other key-value validation code is located.

— — — — — — —

RPC Command

Extensible attributes are set by a single RPC command, called “setstakermeta”. Note that the presence of “meta” in the name might be considered a misnomer because metadata is a somewhat different concept from extensible attributes.

The form of the setstakermeta RPC command is:

setstakerdata <txid> <vout> <alias> <key> <value>

Like other qPoS RPC commands, an unspent transaction output (UTXO) that (1) provides the fees for the transaction and (2) proves authority for setting the attribute, is specified with the “txid” and “vout” parameters, as described in SDBS #10. The “alias” parameter specifies the StealthNode to which the transaction applies, also described in SDBS #10. The “key” and “value” parameters are subject to the constraints described above. Specifying an empty value, deletes the attribute from the StealthNode.

— — — — — — —

Extensible Attribute Transactions

This final section describes how extensible attributes are implemented in the core protocol using the built-in Script interpreter.

Extensible attributes use opcodes and script templates within the Bitcoin-style Script language extension. The opcodes and interpretation for other qPoS transactions (like TX_PURCHASE1, TX_SETOWNER, etc.) are described in the whitepaper. The opcode for extensible attributes is called OP_SETMETA and the transaction type is called TX_SETMETA. The structure of the script template corresponding to TX_SETMETA is:

[size, data(stakerID, key, value), OP_SETMETA]

The size is 60 bytes, consisting of 4 bytes of staker ID plus 16 bytes of the attribute key plus 40 bytes of attribute value. Keys shorter than 16 bytes are null (0x0) terminated, while values shorter than 40 bytes are also null terminated. To favor compression, the reference client pads short keys and values with null bytes at the end, although any other end-padding is valid.

The script template is therefore:

CScript() << OP(0x3c) << OP_SETMETA

— — — — — — —

Hondo

— — — — — — —

Website / Telegram / Slack / Medium / Twitter / Reddit

--

--

Stealth
stealthsend

World’s first private high performance blockchain protocol