RFC-0160/BlockSerialization

Tari Block Binary Serialization

status: stable

Maintainer(s): Stanley Bondi

Licence

The 3-Clause BSD Licence.

Copyright 2021 The Tari Development Community

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of this document must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS DOCUMENT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Language

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY" and "OPTIONAL" in this document are to be interpreted as described in BCP 14 (covering RFC2119 and RFC8174) when, and only when, they appear in all capitals, as shown here.

Disclaimer

This document and its content are intended for information purposes only and may be subject to change or update without notice.

This document may include preliminary concepts that may or may not be in the process of being developed by the Tari community. The release of this document is intended solely for review and discussion by the community of the technological merits of the potential system outlined herein.

Goals

The aim of this Request for Comment (RFC) is to specify the binary serialization of:

  1. a mined Tari block
  2. a Tari block mining template

This is to facilitate interoperability of mining software and hardware.

Specification

By reviewing the block and mining template fields below, we have the following underlying data types for serialization:

  1. bool
  2. u8
  3. u16
  4. u64
  5. i64
  6. array of type [u8; n]
  7. Vec<T> where T is u8, enum or array

For 1. to 5. and all numbers, Base 128 Varint encoding MUST be used.

From the Protocol Buffers documentation:

Varints are a method of serializing integers using one or more bytes. Smaller numbers take a smaller number of bytes. Each byte in a varint, except the last byte, has the most significant bit (msb) set – this indicates that there are further bytes to come. The lower 7 bits of each byte are used to store the two's complement representation of the number in groups of 7 bits, least significant group first.

For 6. to 7., the dynamically sized array and Vec type, the encoded array MUST be preceded by a number indicating the length of the array. This length MUST also be encoded as a varint. By prepending the length of the array, the decoder knows how many elements to decode as part of the sequence.

Block field ordering

Using this varint encoding, all fields of the complete block MUST be encoded in the following order:

  1. Version
  2. Height
  3. Previous block hash
  4. Timestamp
  5. Output Merkle root
  6. Witness Merkle root
  7. Output Merkle mountain range size
  8. Kernel Merkle root
  9. Kernel Merkle mountain range size
  10. Input Merkle root
  11. Total kernel offset
  12. Total script offset
  13. Nonce
  14. Proof of work algorithm
  15. Proof of work supplemental data
  16. Transaction inputs - for each input:
    • Version
    • Spent output - for each output:
      • Version
      • Features
        • Version
        • Maturity
        • Output type
        • Sidechain features
        • Metadata
      • Commitment
      • Script
      • Sender offset public key
      • Covenant
      • Encrypted value
      • Minimum value promise
    • Input data (vector of Stack items)
    • Script signature
  17. Transaction outputs - for each output:
    • Version
    • Features
      • Version
      • Maturity
      • Output type
      • Sidechain features
      • Metadata
    • Commitment
    • Range proof
    • Script
    • Sender offset public key
    • Metadata signature
    • Covenant
    • Encrypted value
    • Minimum value promise
  18. Transaction kernels - for each kernel:
    • Version
    • Features
    • Fee
    • Lock height
    • Excess
    • Excess signature public nonce
    • Excess signature
    • Burn commitment

Mining template field ordering

The new block template is provided to miners to complete. Its fields MUST also be encoded using varints, in the following order:

  1. Version
  2. Height
  3. Previous block hash
  4. Total kernel offset
  5. Total script offset
  6. Proof of work algorithm
  7. Proof of work supplemental data
  8. Transaction inputs - for each input:
    • Version
    • Spent output - for each output:
      • Version
      • Features
        • Version
        • Maturity
        • Output type
        • Sidechain features
        • Metadata
      • Commitment
      • Script
      • Sender offset public key
      • Covenant
      • Encrypted value
      • Minimum value promise
    • Input data (vector of Stack items)
    • Script signature
  9. Transaction outputs - for each output:
    • Version
    • Features
      • Version
      • Maturity
      • Output type
      • Sidechain features
      • Metadata
    • Commitment
    • Range proof
    • Script
    • Sender offset public key
    • Metadata signature
    • Covenant
    • Encrypted value
    • Minimum value promise
  10. Transaction kernels - for each kernel:
    • Version
    • Features
    • Fee
    • Lock height
    • Excess
    • Excess signature public nonce
    • Excess signature
    • Burn commitment
  11. Target difficulty
  12. Reward
  13. Total fees

Value encryption

The value of the value commitment MUST be encrypted using ChaCha20Poly1305 Authenticated Encryption with Additional Data (AEAD). The AEAD key MUST be 32 bytes in size and produced using a domain separated hash of the private key and commitment.

Hash domains

To use a single hash function for producing a sampling of multiple independent hash functions, it's common to employ domain separation. Tari uses the hashing API within the tari codebase to achieve proper hash domain separation.

The following functional areas MUST each use a separate hash domain that is unique in the tari codebase:

  • kernel Merkle Mointain Range;
  • witness MMR;
  • output MMR;
  • input MMR;
  • value encryption.

To achieve interoperability with other blockchains like Bitcoin and Monero, for example an atomic swap, TariScript MUST NOT make use of hash domains.

Tari Block and Mining Template - Data Types

A Tari block is composed of the block header and aggregate body.

Here we describe the respective Rust types of these fields in the tari codebase, and their underlying data types:

Block Header

FieldAbstract TypeData TypeDescription
Versionu16u16The Tari protocol version number, used for soft/hard forks
Heightu64u64Height of this block since the genesis block
Previous Block HashBlockHash[u8;32]Hash of the previous block in the chain
TimestampEpochTimeu64Timestamp at which the block was built (number of seconds since Unix epoch)
Output Merkle RootBlockHash[u8;32]Merkle Root of the unspent transaction ouputs
Witness Merkle RootBlockHash[u8;32]MMR root of the witness proofs
Output MMR Sizeu64u64The size (number of leaves) of the output and range proof MMRs at the time of this header
Kernel Merkle RootBlockHash[u8;32]MMR root of the transaction kernels
Kernel MMR Sizeu64u64Number of leaves in the kernel MMR
Input Merkle RootBlockHash[u8;32]Merkle Root of the transaction inputs in this block
Total Kernel OffsetBlindingFactor[u8;32]Sum of kernel offsets for all transaction kernels in this block
Total Script OffsetBlindingFactor[u8;32]Sum of script offsets for all transaction kernels in this block
Nonceu64u64Nonce increment used to mine this block
PowProofOfWorkSee Proof Of WorkProof of Work information

[u8;32] indicates an array of 32 unsigned 8-bit integers

Proof Of Work

FieldAbstract TypeData TypeDescription
Proof of Work AlgorithmPowAlgorithmu8The algorithm used to mine this block ((Monero or SHA3))
Proof of Work DataVec<u8>u8Supplemental proof of work data. For example for Sha3, this would be empty (only the block header is required), but for Monero merge mining we need the Monero block header and RandomX seed hash

Block Body

FieldAbstract TypeData TypeDescription
SortedboolboolTrue if sorted
Transaction InputsVec<TransactionInput>TransactionInputList of inputs spent
Transaction OutputsVec<TransactionOutput>TransactionOutputList of outputs produced
Transaction KernelsVec<TransactionKernel>TransactionKernelKernels contain the excesses and their signatures for the transactions

A further breakdown of the body fields is described below:

TransactionInput

FieldAbstract TypeData TypeDescription
VersionTransactionInputVersionu16The features of the output being spent. We will check maturity for all outputs.
Spent OutputSpentOutputSee SpentOutputEither the hash of TransactionOutput that this Input is spending or its data
Input DataExecutionStackVec<u8>The script input data, maximum size is 512
Script SignatureCommitmentAndPublicKeySignatureSee CommitmentAndPublicKeySignatureA signature signing the script and all other transaction input metadata with the script private key
SpentOutput
FieldAbstract TypeData TypeDescription
OutputHashHashOutput[u8;32]The features of the output being spent. We will check maturity for all outputs.
VersionTransactionOutputVersionu8The TransactionOutput version
FeaturesOutputFeaturesSee OutputFeaturesOptions for the output's structure or use
CommitmentPedersenCommitment[u8;32]The commitment referencing the output being spent.
ScriptTariScriptVec<u8>The serialised script, maximum size is 512
Sender Offset Public KeyCommitmentAndPublicKeySignature[u8;32]The Tari script sender offset public key
CovenantVec<CovenantToken>See CovenantTokenA future-based contract detailing input and output metadata
Encrypted ValueEncryptedValue[u8;24]The encrypted value of the value commitment
Minimum Value PromiseMicroTariu64 (See Value encryption)The minimum value promise embedded in the range proof
CommitmentAndPublicKeySignature
FieldAbstract TypeData TypeDescription
Public NoncePedersenCommitment[u8;32]The public (Pedersen) commitment nonce created with the two random nonces
uSecretKey[u8;32]The first publicly known private key of the signature signing with the value
vSecretKey[u8;32]The second publicly known private key of the signature signing with the blinding factor
Public KeyPedersenCommitment[u8;32]The public nonce of the Schnorr signature
aSecretKey[u8;32]The publicly known private key of the Schnorr signature

Find out more about CommitmentAndPublicKey signatures:

OutputFeatures
FieldAbstract TypeData TypeDescription
VersionOutputFeaturesVersionu8The OutputFeatures version
Output TypeOutputTypeu8The type of output
Maturityu64u64The block height at which the output can be spent
MetadataVec<u8>u8The block height at which the output can be spent
Side-chain FeaturesSideChainFeaturesnoneNot implemented
CovenantToken
FieldAbstract TypeData TypeDescription
FilterCovenantFilterSee CovenantFilterThe covenant filter
ArgCovenantArgSee CovenantArgThe covenant argument(s)
CovenantFilter
FieldAbstract TypeData TypeDescription
IdentityIdentityFilternoneThe Identity
AndAndFilternoneAnd operation
OrOrFilternoneOr operation
XorXorFilternoneXor operation
NotNotFilternoneNot operation
Output Hash EqualOutputHashEqFilternoneOutput hash to be equal to
Fields PreservedFieldsPreservedFilternoneFields to be preserved
Field EqualFieldEqFilternoneField to be equal to
Fields Hashed EqualFieldsHashedEqFilternoneFields hashed to be equal to
Absolute HeightAbsoluteHeightFilternoneAbsolute height
CovenantArg
FieldAbstract TypeData TypeDescription
HashFixedHash[u8;32]Future hash value
PublicKeyPublicKey[u8;32]Future public key
CommitmentPedersenCommitment[u8;32]Future commitment referencing the output being spent.
Tari ScriptTariScriptVec<u8>Future serialised script, maximum size is 512
CovenantVec<CovenantToken>See CovenantTokenFuture covenant
Output TypeOutputTypeu8Future type of output
UintUintu64Future value
Output FieldOutputFieldSee OutputFieldFuture set of output fields
OutputFieldsVec<OutputField>See OutputFieldFuture set of output fields
BytesVec<u8>u8Future raw data
OutputField
FieldAbstract TypeData TypeDescription
Commitmentu8u8Commitment byte code
Scriptu8u8Script byte code
Sender Offset Public Keyu8u8SenderOffsetPublicKey byte code
Covenantu8u8Covenant byte code
Featuresu8u8Features byte code
Features Output Typeu8u8FeaturesOutputType byte code
Features Maturityu8u8FeaturesMaturity byte code
Features Metadatau8u8FeaturesMetadata byte code
Features Side Chain Featuresu8u8FeaturesSideChainFeatures byte code

TransactionOutput

FieldAbstract TypeData TypeDescription
VersionTransactionOutputVersionu8The TransactionOutput version
FeaturesOutputFeaturesSee OutputFeaturesOptions for the output's structure or use
CommitmentPedersenCommitment[u8;32]The homomorphic commitment representing the output amount
ProofRangeProofVec<u8>A proof that the commitment is in the right range
ScriptTariScriptVec<u8>The script that will be executed when spending this output
Sender Offset Public KeyPublicKey[u8;32]The Tari script sender offset public key
Metadata SignatureCommitmentAndPublicKeySignatureSee CommitmentAndPublicKeySignatureA signature signing all transaction output metadata with the script offset private key and spending key
CovenantVec<CovenantToken>See CovenantTokenA future-based contract detailing input and output metadata
Encrypted ValueEncryptedValue[u8;24]The encrypted value of the value commitment
Minimum Value PromiseMicroTariu64 (See Value encryption)The minimum value promise embedded in the range proof

TransactionKernel

FieldAbstract TypeData TypeDescription
VersionTransactionKernelVersionu8The TransactionKernel version
FeaturesKernelFeaturesu8Options for a kernel's structure or use
FeeMicroTariu64Fee originally included in the transaction this proof is for.
Lock Heightu64u64This kernel is not valid earlier than this height. The max maturity of all inputs to this transaction
ExcessPedersenCommitment[u8;32]Remainder of the sum of all transaction commitments (minus an offset). If the transaction is well-formed, amounts plus fee will sum to zero, and the excess is a valid public key
Excess SignatureRistrettoSchnorrSee RistrettoSchnorrAn aggregated signature of the metadata in this kernel, signed by the individual excess values and the offset excess of the sender
Burn CommitmentPedersenCommitment[u8;32]This is an optional field that must be set if the transaction contains a burned output

RistrettoSchnorr

FieldAbstract TypeData TypeDescription
Public noncePublicKey[u8;32]The public nonce of the Schnorr signature
SignatureSecretKey[u8;32]The signature of the Schnorr signature

New Block Template

The new block template is used in constructing a new partial block, allowing a miner to add the coinbase UTXO and as a final step for the Base node to add the MMR roots to the header.

FieldAbstract TypeData TypeDescription
HeaderNewBlockHeaderTemplateSee New Block Header TemplateThe Tari protocol version number, used for soft/hard forks
BodyAggregateBodySee Block BodyHeight of this block since the genesis block
Target DifficultyDifficultyu64The minimum difficulty required to satisfy the Proof of Work for the block
RewardMicroTariu64The value of the emission for the coinbase output for the block
Total FeesMicroTariu64The sum of all transaction fees in this block

New Block Header Template

FieldAbstract TypeData TypeDescription
Versionu16u16The Tari protocol version number, used for soft/hard forks
Heightu64u64Height of this block since the genesis block
Previous HashBlockHash[u8;32]Hash of the previous block in the chain
Total Kernel OffsetBlindingFactor[u8;32]Total accumulated sum of kernel offsets since genesis block. We can derive the kernel offset sum for this block from the total kernel offset of the previous block header.
Total Script OffsetBlindingFactor[u8;32]Sum of script offsets for all transaction kernels in this block
PowProofOfWorkSee Proof Of WorkProof of Work information