Diamante Data Structures

The fundamental data structures and building blocks present on the Diamante network.

Ledgers

A ledger in the Diamante network represents the state of the Diamante network at a specific point in time. It is shared across all Core nodes in the network and contains information about accounts and balances, orders on the distributed exchange, operations data, and any other persisting data.

In other blockchains, this concept is often referred to as a "block", and the entire blockchain is sometimes called "the ledger".

In every Diamante Consensus Protocol round, the network reaches consensus on which transaction set to apply to the last closed ledger. When the new set is applied, a new "last closed ledger" is defined. Each ledger is cryptographically linked to the unique previous ledger, creating a historical chain that goes back to the genesis ledger.

Data within the ledger is stored as ledger entries. Possible ledger entries in Diamante include:

  • Accounts
  • Claimable balances
  • Liquidity pools

Every ledger has a ledger header. To learn more about what is contained in the ledger header, refer to our, Encyclopedia-> Ledger Header.

Accounts

Accounts are a fundamental data structure in the Diamante network, responsible for holding balances, signing transactions, and issuing assets. An account can only exist with a valid keypair and must maintain the required minimum balance of DIAM (Diamante's native cryptocurrency). For information regarding minimum balance requirements, refer to the Diamante Diams Section.

Account Fields

  1. Account ID: A unique identifier for the account.
  2. Balances: The balances held within the account.
  3. Flags: Flags associated with the account.
  4. Home Domain (up to 32 characters): A domain associated with the account.
  5. Liabilities: Liabilities information for the account.
  6. Number of entries sponsored by this account: Total entries sponsored by this account.
  7. Number of sponsored reserves: The count of sponsored reserves.
  8. Number of subentries: The number of subentries within the account.
  9. Sequence number: The sequence number of the account.
  10. Signers: Information about signers associated with the account.
  11. Thresholds: Threshold values for the account.
  12. Base reserves and subentries: Account data stored in subentries, where each subentry increases the account's minimum balance.

Base Reserves

A base reserve is a unit of measurement used to calculate an account’s minimum balance in Diamante. Currently, one base reserve is equivalent to 0.0000002 DIAM.

Subentries

Account data is organized in subentries, where each subentry incrementally increases the account’s minimum balance by one base reserve (0.0000002 DIAM). An account is limited to a maximum of 1,000 subentries. Possible subentries include:

  • Trustlines (for traditional assets and pool shares)
  • Offers
  • Additional signers
  • Data entries (created with the manageData operation, not smart contract ledger entries)

Trustlines

Trustlines are an explicit opt-in for an account to hold and trade a specific asset in Diamante. To hold a particular asset, an account must establish a trustline with the issuing account using the change_trust operation. Trustlines track the balance of an asset and can also impose limits on the amount of an asset that an account can hold.

For an account to receive any asset except the native DIAM, a trustline must be established. While you can create a claimable balance to send assets to an account without a trustline, the recipient must create a trustline to claim that balance. Refer to the Claimable Balances Encyclopedia Entry for more information.

Trustlines also track liabilities, including buying liabilities and selling liabilities. An account's trustline must always have a balance sufficiently large to satisfy its selling liabilities and a balance sufficiently below its limit to accommodate its buying liabilities.

Assets

Assets are a core concept in the Diamnet blockchain, where assets can represent a wide range of values. These assets can be cryptocurrencies, fiat currencies, tokens (such as NFTs), pool shares, bonds, equity, and many more. In Diamante, assets provide a way to model various types of value or ownership within the network.

Identifying Characteristics

Assets on Diamante have two primary identifying characteristics: the asset code and the issuer. Since multiple organizations can issue a credit representing the same asset, asset codes often overlap. Assets are uniquely identified by the combination of their asset code and issuer.

These characteristics are critical when performing transactions or interacting with assets on the Diamnet blockchain.

The process of Naming an Asset in Diamante is a critical step when issuing an asset, and the format of the asset code is an essential aspect to understand. Let me break down the different naming conventions and formats:

Naming an Asset

When creating an asset on Diamante, you must decide on an asset code. This code will uniquely identify the asset in the Diamante blockchain and is an important part of the asset’s structure.

Formats for Asset Codes

There are three main formats for naming an asset:

  1. Alphanumeric 4-Character Maximum:
    • This format allows for asset codes that are up to 4 characters long.
    • The code can contain any combination of the characters from the set a-z, A-Z, and 0-9.
    • The asset code can be shorter than 4 characters, but the trailing characters must be empty (e.g., "BTC " or "USD "). This means you can use fewer than 4 characters, but any unused characters in the 4-character slot must be left blank.
  2. Alphanumeric 12-Character Maximum:
    • This format is for asset codes that are between 5 and 12 characters long.
    • Again, any combination of characters from the set a-z, A-Z, and 0-9 can be used.
    • If the code is shorter than 12 characters, trailing characters must be empty (e.g., "USDSTABLE" or "STKXYZ ").
  3. Liquidity Pool Shares:
    • In the case of liquidity pool shares, the asset code is not arbitrary.
    • The pool share asset is defined by the liquidity pool identifier (PoolID), which is derived from the two assets that the pool reserves are composed of.
    • The naming convention here directly references the liquidity pool, ensuring it is tied to the pool's assets and structure.
Asset Code :
  • The Asset Code is a unique identifier for an asset in the Diamnet blockchain. It typically consists of an alphanumeric string (up to 12 characters) that represents the asset's type or name. For example, an asset code could be "USD" for a fiat-backed asset or "DIAM" for the native Diamnet token.
  • Asset codes can be easily recognized and used to distinguish between different assets, such as currencies, tokens, or even NFTs.
Issuer :
  • The Issuer is the account that creates and controls the asset. It’s often the entity or individual who is responsible for the asset’s properties and governs its issuance.
  • In the case of a stablecoin like USD-backed assets, the issuer would typically be a trusted authority like a bank or financial institution and would rely on a trusted issuer account.

Asset Components:

Assets in Diamante are composed of the following key components:

  • Asset Code: The identifier that distinguishes the asset type (e.g., DIAM, USD).
  • Issuer: The account or entity responsible for the creation and management of the asset.
  • Amount Precision: Defines the granularity of the asset’s smallest unit (e.g., 0.0001 for fine precision).
  • Quantity: This refers to the amount of the asset being transferred or held in an account, which is determined by the issuer’s policies and amount precision.

Representation:

In aurora, assets are represented in a JSON object:

                            {
                                asset_code: "DiamanteToken",
                                asset_issuer: "GC2BKLYOOYPDEFJKLKY6FNNRQMGFLVHJKQRGNSSRRGSMPGF32LHCQVGF",
                                // `asset_type` is used to determine how asset data is stored.
                                // It can be `native` (Diams), `credit_alphanum4`, or `credit_alphanum12`.
                                asset_type: "credit_alphanum12",
                            }
                        

Amount Precision

Each asset amount is encoded as a signed 64-bit integer in the XDR structures used by Diamante to encode transactions. The asset amount unit seen by end-users is scaled down by a factor of ten million (10,000,000) to arrive at the native 64-bit integer representation.

For example, the integer amount value 25,123,456 equals 2.5123456 units of the asset. This scaling allows for seven decimal places of precision in human-friendly amount units.

The smallest non-zero amount unit, also known as a jot, is 0.0000001 (one ten-millionth) represented as an integer value of one. The largest amount unit possible is 922,337,203,685.4775807.

Relevance in aurora and Diamante Client Libraries

In aurora and client-side libraries such as js-diamante-sdk, the integer encoded value is abstracted away. Many APIs expect an amount in unit value (the scaled-up amount displayed to end-users). Some programming languages (such as go) have problems maintaining precision on a number amount. It is recommended to use "big number" libraries that can record arbitrary-precision decimal numbers without a loss of precision.

Deleting or Burning Assets

  • Burning Assets: Burning refers to the process of permanently removing an asset from circulation. This can be done by sending the asset to an address that cannot be spent from (a "burn address"). In Diamante, burning may be used to reduce supply, stabilize value, or facilitate other protocols such as deflationary mechanisms.
  • Deleting Assets: Deleting assets can occur when the issuer decides to deprecate or remove an asset entirely from the network. However, this is less common than burning, as it involves the issuer removing all traces of the asset, including its associated ledger entries and transactions.

Operations & Transactions

How they work

To perform actions with an account on the Diamante network, you compose operations, bundle them into a transaction, and then sign and submit the transaction to the network. We can perform (1 - 100) operations per transaction.

Operations

Operations are individual commands that modify the ledger. Operations are used to send payments , enter orders into the decentralized exchange, change settings on accounts, and authorize accounts to hold assets.

All operations fall into one of three threshold categories: low, medium, or high, and each threshold category has a weight between 0 and 255 (which can be determined using set_options). Thresholds determine what signature weight is required for the operation to be accepted. For example, let’s say an account sets the medium threshold weight to 5. If the account wants to successfully establish a trustline with the changeTrust operation, the weight of the signature(s) must be greater than or equal to 5.

To learn more about signature weight, see the Signature and Multisignature Encyclopedia Entry.

View a comprehensive list of Diamante operations and their threshold levels in the List of Operations section.

Transactions

The Diamante network encodes transactions using a standardized protocol called External Data Representation (XDR). You can read more about this in our XDR Encyclopedia Entry.

Accounts can only perform one transaction at a time. Transactions comprise a bundle of between 1-100 operations and are signed and submitted to the ledger by accounts. Transactions always need to be authorized by the source account’s public key to be valid, which involves signing the transaction object with the public key’s associated private key.

secret key. A transaction plus its signature(s) is called a transaction envelope.

A transaction may need more than one signature- this happens if it has operations that affect more than one account or if it has a high threshold weight. Check out the Signature and Multisignature Encyclopedia Entry for more information.

Transactions are atomic: meaning if one operation in a transaction fails, all operations fail, and the entire transaction is not applied to the ledger.

Operations are executed for the source account of the transaction unless an operation override is defined.

Transaction Attributes

  • Fee
  • List of Operations
  • List of Signatures
  • Memo or Muxed Account
  • Sequence Number
  • Source Account

Transaction and operation validity

Before being successfully submitted to the Diamante network, transactions go through several validity checks. These checks are grouped into three categories:

Preconditions (Optional)

Time Bounds

Valid if within set time bounds of the transaction

Time bounds are an optional UNIX timestamp (in seconds), determined by ledger time, of a lower and upper bound of when a transaction will be valid. If a transaction is submitted too early or too late, it will fail to make it into the transaction set. Setting time bounds on transactions is highly encouraged, and many SDKs enforce them.

If maxTime is 0, upper time bounds are not set. In this case, if a transaction does not make it to the transaction set, it is kept in memory and continuously tries to make it to the next transaction set. Because of this, we advise that all transactions are created with time bounds to invalidate transactions after a certain amount of time, especially if you plan to resubmit your transaction at a later time.

Ledger Bounds

Valid if within set ledger bounds of the transaction

Ledger bounds apply to ledger numbers. With these defined, a transaction will only be valid for ledger numbers that fall within the determined range.

Minimum Sequence Number

If a minimum sequence number is set, the transaction will only be valid when its source account’s sequence number (call it S) is large enough. Specifically, it’s valid when S satisfies minSeqNum <= S < tx_seqNum.

If this precondition is omitted, the default behaviour applies: the transaction’s sequence number must be exactly one greater than the account’s sequence number.

Minimum Sequence Age

Transaction is valid after a particular duration (expressed in seconds) elapses since the account’s sequence number’s age.

Minimum Sequence Ledger Gap

Valid if submitted in a ledger meeting or exceeding the source account’s sequence number age

Extra Signers

Valid if submitted with signatures that fulfill each of the extra signers

Operation Validity

When a transaction is submitted to a node, the node checks the validity of each operation in the transaction before attempting to include it in a candidate transaction set. These initial operation validity checks are intended to be fast and simple, with more intensive checks coming after the fees have been consumed.

For an operation to pass this validity check, it has to meet the following conditions:

  • The signatures on the transaction must be valid for the operation: The signatures are from valid signers for the source account of the operation. The combined weight of all signatures for the source account of the operation meets the threshold for the operation.
  • The operation must be well-formed: Typically, this means checking the parameters for the operation to see if they’re in a valid format. For example, only positive values can be set for the amount of a payment operation.
  • The operation must be valid in the current protocol version of the network. Deprecated operations, such as inflation, are invalid by design.

Transaction Validity

Finally, the following transaction checks take place:

  • Source account: The source account must exist on the ledger.
  • Fee: The fee must be greater than or equal to the network minimum fee for the number of operations submitted as part of the transaction.
  • Fee-bump: See Validity of a Fee-Bump Transaction section.
  • Sequence number: The sequence number must be one greater than the sequence number stored in the source account entry when the transaction is applied unless sequence number preconditions are set. When checking the validity of multiple transactions with the same source account in a candidate transaction set, they must all be valid transactions and their sequence numbers must be offset by one. Then they are ordered and applied according to their sequence number.
  • List of Operations: Each operation must pass all the validity checks for an operation, described in the Operation Validity section above.

List of Signatures:

  • Meet signature requirements for each operation in the transaction
  • Appropriate network passphrase is part of the transaction hash signed by each signer
  • Combined weight of the signatures for the source account of the transaction meets the low threshold for the source account.

Memo (if applicable):

  • The memo type must be a valid type, and the memo itself must adhere to the formatting of the memo type.