Stealth Development Blog 011: 02/22/2019
Stealth qPoS Enters Testing
Today, I am excited to say that after a painful week of fixing compiling errors, we have the first functional build of the qPoS client. Not only does it build without error, but as of a few hours ago, it has created a testnet genesis block, meaning that the Internal Testnet is operational.
–––––
Development Wish List
The path to mainnet (i.e. my wish list) is outlined in SDBS 009 and is summarized as follows:
☑ Implement the RPC commands.
☑ Build the client (debug the compiling process).
☑ Get it to run and create a testnet genesis block (meaning it can boot!).
☒ Run the Internal Testnet that tests all functionalities of the client.
☐ Implement blockwise Byzantine fault tolerance (BFT) .
☐ Public Testnet Phase 1, with code publication to github
☐ Public Testnet Phase 2
☐ Staker bad behavior controls and maybe qPoS GUI
☐ Public Testnet Phase 3 with participation incentives (KYC applies)
☐ Main Net Release
Key
☐ – Not started yet
☒ – In progress
☑ – Complete
Note that all disclaimers in SDBS 009 still apply.
–––––
Pseudo-Schema of
getqposinfo
JSON Output
Even though debugging a build with so much new code takes a lot of work, it doesn’t catalyze much in the way of design decisions or new functionalities. Also, I want to get to testing my new creation ASAP, so I don’t feel like writing a long-winded post about cryptocurrency concepts today.
Instead, I present a detailed description and pseudo-schema for getqposinfo
, which will be highly useful for third party service providers. After all, the SDBS is meant to document as much as give updates on progress. The material for this documentation comes from the fact that I needed to document the output of the most useful informational qPoS RPC command, getqposinfo
for a third party who may (no promises!) be working with Stealth on app development.
Please note that I published a mock-up of the output of getqposinfo
as a github gist. The entire output of getqposinfo
is a single JSON object with the following hierarchy:
Registry Object (Top-Level)
- version: [integer] This top-level version is the registry data structure version, and may give an indication of available JSON fields in the future.
- block_height: [integer] Height of latest block to which the registry is updated.
- block_hash: [string] Hex encoded 64 character (32 byte/256 bit) hash of latest block.
- in_replay: [bool] This value is
true
if the registry is being replayed, which happens during restart and reorganization of the chain. - counter_next: [integer] Next staker ID for a newly created staker.
- current_block_was_produced: [bool] Each slot corresponds to a block that should be produced, but may not be produced if a staker missed it. This field will be
true
if a staker has produced a block for the current time slot of the queue. The staker registry is updated in real time. When a time slot has expired and a new block has not yet been produced by the assigned staker, this field will have a value offalse
.
prev_block_was_produced: [bool] Whether the block for the previous time slot was produced. The concept of previous blocks is discussed below forprev_blocks_missed
and in SDBS 001, in the context of discouraging staker timestamp attacks. - current_slot: [integer] Each slot of the queue schedule has an index, starting with 0. The value of
current_slot
is the index of the current slot in the queue. The queue is described below. - staker_price: [float] Real-time price of a staker in XST. The price fluctuates from block to block.
- queue: [array of objects] Represents the current round of staking where stakers are pseudo-randomly shuffled, signing blocks in shuffled order. Each component object of this array has the keys id, start_time, and end_time, described below under the heading Queue Object.
- stakers: [object] An object with staker IDs as keys. Although IDs are integers, as JSON keys, they must be represented as strings. Each component object represents a staker and is described below under the heading Staker Object.
- balances: [object] Represents the balances tracked in the registry ledger, which stores payouts to staker owners and their delegates. JSON keys are pubkeys (hex encoded 66 character strings). Each component object is described below under the heading Balances Object.
Queue Object
- id: [integer] Staker ID, which is a unique number from an increment counter tracked by the registry.
- start_time: [integer] Timestamp (seconds) of the start of the slot.
- end_time: [integer] Timestamp (seconds) of the end of the slot.
Staker Object
- alias: [string] Unique, case-sensitive staker alias, as assigned by the registrant, and can never change.
- id: [integer] Staker ID.
- version: Version of the staker data structure, and may give an indication of the available staker fields in the future.
- qualified: [bool] If
false
(rare), the staker will be terminated and purged from the registry at the end of the current round. Staking rounds are tracked in the queue, described above. - enabled: [bool] Stakers can be enabled (
true
) and disabled (false
). A disabled staker is essentially in hibernation. A disabled staker will not be assigned a position in the queue, will not be penalized for missing blocks, and will not earn any block rewards. - weight: [integer] Payout and chain trust multiplier, each staker has a potentially unique multiplier. As described in the Whitepaper, weight is proportional to the staker’s net blocks produced, where each missed block is subtracted from the total produced. A staker earns rewards proportional to its weight. Additionally, chain trust is additive, where the weight of a staker producing a block is the block’s trust.
- keys: [object] Describes the authority keys for a staker. This object has the following JSON keys: owner_key, delegate_key, and controller_key. This object is described below under the heading Keys Object
- delegate_payout_pcm: [integer] Fraction of rewards paid to delegate in milli-percent (per cent mille, pcm). E.g. 10,000 pcm = 10%. Maximum value is 100,000.
- total_earned: [integer] Total XST earned by the staker. This includes payouts to both the owner and delegate.
- blocks_produced: [integer] Total blocks produced by the staker.
- blocks_missed: [integer] Total blocks missed by the staker.
- blocks_assigned: [integer] Total blocks assigned to the staker (produced + missed).
- blocks_seen: [integer] Total blocks that have been added to the chain since the staker was created. This value is “how old the staker is” in blocks.
- prev_blocks_missed: [integer] Total blocks missed by the staker in the slot immediately prior in the queue. Every round a new queue is made with stakers in pseudo-random order. A staker is immediately prior ("previous") to another if it comes in the queue exactly one slot earlier, meaning the identity of a “previous” staker will vary according to the pseudo-random ordering of the queue. The qPoS protocol tracks misses of "previous" stakers because a staker can behave badly to attempt to fool the network into thinking the "previous" staker missed a block. See SDBS 001.
- recent_blocks: [array of integers] Components of this array are 1 or 0, exclusively. The value 1 means the staker produced its assigned block. The value 0 means the staker missed its assigned block. This array is in reverse-chronological order where more recent blocks have lower indices in the array. These blocks are based on assignments to the specific staker, and are not contiguous. In other words the block represented by element 0 in the
recent_blocks
array does not necessarily immediately follow (in the blockchain) the block corresponding to element 1. For example, if element 0 represents block 1000, element 1 may represent block 970, if both blocks 1000 and 970 were assigned to the staker, with no assignments between. - prev_recent_blocks: [array of integers] Similar to
recent_blocks
, but representing the blocks assigned to the staker’s previous slots. See theprev_blocks_missed
description above for the meaning of “previous” in this context.
Keys Object
- owner_key: [string] Hex encoded 66 character (33 byte) hash of the staker’s owner key. The owner key can change all three authority keys. If the owner key is changed, it transfers ownership. Payout from block rewards is indicated by the
delegate_payout_pcm
value, described below. - delegate_key: [string] Hex encoded 66 character (33 byte) hash of the staker’s delegate key. As described in SDBS 001, a delegate has authority to sign blocks on behalf of the staker’s owner. Payout to the delegate is subject to the
delegate_payout_pcm
value. - controller_key: [string] Hex encoded 66 character (33 byte) hash of the staker’s controller key. As described in SDBS 003, a controller can enable and disable a staker for purposes like failover safety.
Balances Object
- balance: [float] The unclaimed balance belonging to the pubkey.
- last_claim: [integer] Timestamp (seconds) of the last claim of this pubkey’s balance. Each pubkey can make a claim no more frequently than every 24 hours. The reason for this imposed infrequency is that each claim creates a new UTXO. So, to allow unlimited claims would defeat the purpose of qPoS’s hybrid ledger, which has as one component a registry ledger with no UTXOs. This maximizes efficiency of the qPoS protocol.
- active_count: [integer] Each pubkey can be associated with any number of owners and delegates. The
active_count
keeps track of how many extant staker owners plus delegates are assigned to the key.
–––––
Hondo