The Vtxo type represents a virtual UTXO in the Ark protocol. VTXOs are off-chain constructs that can be spent cooperatively with the server or unilaterally exited on-chain.
Overview
VTXOs form the fundamental unit of value in Ark. Each VTXO contains:
An output policy defining spending conditions
An amount of Bitcoin
A chain anchor linking to on-chain confirmation
Genesis data describing how the VTXO was created
The correctness of methods on Vtxo is conditional on the VTXO being valid. Always validate VTXOs upon receipt using validate().
Core Type: Vtxo
pub struct Vtxo < P = VtxoPolicy > {
policy : P ,
amount : Amount ,
expiry_height : BlockHeight ,
server_pubkey : PublicKey ,
exit_delta : BlockDelta ,
anchor_point : OutPoint ,
genesis : Vec < GenesisItem >,
point : OutPoint ,
}
Key Methods
Identification
pub fn id ( & self ) -> VtxoId
Get the unique identifier for this VTXO (same as point() but encoded as bytes).
pub fn point ( & self ) -> OutPoint
The outpoint from which to build forfeit or arkoor transactions.
Value and Ownership
pub fn amount ( & self ) -> Amount
The amount of Bitcoin in this VTXO.
pub fn user_pubkey ( & self ) -> PublicKey
Returns the user public key associated with this VTXO.
pub fn arkoor_pubkey ( & self ) -> Option < PublicKey >
The public key used to cosign arkoor (out-of-round) transactions. Returns None if the policy is not arkoor-compatible.
Chain Anchoring
pub fn chain_anchor ( & self ) -> OutPoint
The UTXO that must be confirmed on-chain for this VTXO to be valid. This is the root of the VTXO’s exit transaction tree.
Policy and Expiry
pub fn policy ( & self ) -> & P
Access the output policy of this VTXO.
pub fn policy_type ( & self ) -> VtxoPolicyKind
Get the type of policy (Pubkey, ServerHtlcSend, ServerHtlcRecv, etc.).
pub fn expiry_height ( & self ) -> BlockHeight
The block height at which the VTXO expires and the server can sweep funds.
pub fn exit_delta ( & self ) -> BlockDelta
The relative timelock block delta required for unilateral exits.
pub fn exit_depth ( & self ) -> u16
Returns the total exit depth (number of transactions) including OOR transitions.
Transaction Construction
pub fn output_taproot ( & self ) -> TaprootSpendInfo
The taproot spend info for the output of this VTXO.
pub fn output_script_pubkey ( & self ) -> ScriptBuf
The scriptPubkey of the VTXO output.
pub fn txout ( & self ) -> TxOut
The transaction output (eventual UTXO) of this VTXO.
pub fn transactions ( & self ) -> VtxoTxIter <' _ , P >
Iterator that constructs all exit transactions for this VTXO, starting from the chain anchor.
Validation
pub fn validate ( & self , chain_anchor_tx : & Transaction ) -> Result <(), VtxoValidationError >
Fully validate this VTXO and its entire transaction chain, including all signatures.
chain_anchor_tx: The transaction with txid matching chain_anchor()
pub fn validate_unsigned ( & self , chain_anchor_tx : & Transaction ) -> Result <(), VtxoValidationError >
Validate VTXO structure without checking signatures.
pub fn has_all_witnesses ( & self ) -> bool
Whether all transaction witnesses are present. Returns false for unsigned or unfinished VTXOs.
pub fn is_standard ( & self ) -> bool
Check if this VTXO is standard for relay purposes:
Its own output is standard
All sibling outputs in the exit path are standard
Each part of the exit path has a P2A (pay-to-anchor) output
VtxoId
A unique 36-byte identifier for a VTXO.
pub struct VtxoId ([ u8 ; 36 ]);
Methods:
pub fn from_slice ( b : & [ u8 ]) -> Result < VtxoId , VtxoIdParseError >
Construct from a byte slice (must be exactly 36 bytes).
pub fn utxo ( self ) -> OutPoint
Convert to the underlying OutPoint.
pub fn to_bytes ( self ) -> [ u8 ; 36 ]
Get the raw 36-byte representation.
VtxoSpec
Specifies a VTXO independent of its origin.
pub struct VtxoSpec < P = VtxoPolicy > {
pub policy : P ,
pub amount : Amount ,
pub expiry_height : BlockHeight ,
pub server_pubkey : PublicKey ,
pub exit_delta : BlockDelta ,
}
Methods:
pub fn output_taproot ( & self ) -> TaprootSpendInfo
The taproot spend info for this VTXO’s output.
pub fn output_script_pubkey ( & self ) -> ScriptBuf
The scriptPubkey of this VTXO’s output.
pub fn txout ( & self ) -> TxOut
The transaction output for this VTXO.
VtxoRequest
A request to create a VTXO with a specific policy and amount.
pub struct VtxoRequest {
pub policy : VtxoPolicy ,
pub amount : Amount ,
}
Used when requesting VTXOs in rounds or other operations.
ServerVtxo
Type alias for server-internal VTXOs that may have policies without user pubkeys.
pub type ServerVtxo = Vtxo < ServerVtxoPolicy >;
Server VTXOs can represent intermediate states like checkpoints or expiry-only outputs.
Genesis Data
Each VTXO contains genesis data describing how it was created.
GenesisItem
pub struct GenesisItem {
pub transition : GenesisTransition ,
pub output_idx : u8 ,
pub other_outputs : Vec < TxOut >,
pub fee_amount : Amount ,
}
Represents one level in the VTXO’s exit transaction chain.
Fields:
transition: The type of transition (Cosigned, Arkoor, HashLockedCosigned)
output_idx: Which output in the transaction goes to the next level
other_outputs: Sibling outputs needed to reconstruct the transaction
fee_amount: Fee for the P2A output (usually zero except for boarding)
GenesisTransition
pub enum GenesisTransition {
Cosigned ( CosignedGenesis ),
HashLockedCosigned ( HashLockedCosignedGenesis ),
Arkoor ( ArkoorGenesis ),
}
Cosigned : A transition based on a MuSig cosignature. Used for:
Round tree branch transitions (clArk)
Board operations cosigned with the server
pub struct CosignedGenesis {
pub pubkeys : Vec < PublicKey >,
pub signature : Option < schnorr :: Signature >,
}
HashLockedCosigned : A transition requiring both a signature and hash preimage. Used for hArk (hash-locked Ark) leaf outputs.pub struct HashLockedCosignedGenesis {
pub user_pubkey : PublicKey ,
pub signature : Option < schnorr :: Signature >,
pub unlock : MaybePreimage ,
}
Arkoor : An out-of-round spend using co-signed p2tr keyspend.pub struct ArkoorGenesis {
pub client_cosigners : Vec < PublicKey >,
pub tap_tweak : TapTweakHash ,
pub signature : Option < schnorr :: Signature >,
}
Protocol Encoding
VTXOs use a stable binary encoding for network transmission and storage.
Current version : 2 (version 1 lacked fee amounts in genesis items)
const VTXO_ENCODING_VERSION : u16 = 2 ;
Version (u16)
Amount (u64, satoshis)
Expiry height (u32)
Server pubkey (33 bytes)
Exit delta (u16)
Anchor point (36 bytes)
Genesis items (compact size + items)
Policy (variable)
Point (36 bytes)
Each genesis item encodes:
Transition type and data
Number of outputs (u8)
Output index (u8)
Other outputs (variable)
Fee amount (u64, satoshis)
Usage Examples
Validating a VTXO
let vtxo : Vtxo = // ... received from server or peer
let chain_anchor_tx : Transaction = // ... fetch from chain
// Validate the entire VTXO
vtxo . validate ( & chain_anchor_tx ) ? ;
// Check key properties
assert! ( vtxo . is_standard ());
assert! ( vtxo . has_all_witnesses ());
assert_eq! ( vtxo . amount (), Amount :: from_sat ( 100_000 ));
Constructing Exit Transactions
// Iterate through all exit transactions
for tx_item in vtxo . transactions () {
println! ( "Exit tx: {}" , tx_item . tx . compute_txid ());
println! ( "Output index: {}" , tx_item . output_idx);
}
// Get the final VTXO output
let final_output = vtxo . txout ();
println! ( "Final scriptPubkey: {}" , final_output . script_pubkey);
Checking VTXO Properties
// Check policy compatibility
if let Some ( arkoor_pk ) = vtxo . arkoor_pubkey () {
println! ( "VTXO can be spent out-of-round with key: {}" , arkoor_pk );
}
// Check expiry
let current_height = 850_000 ;
if current_height >= vtxo . expiry_height () {
println! ( "VTXO has expired, server can sweep" );
}
// Check exit depth
println! ( "Exit requires {} transactions" , vtxo . exit_depth ());
Important Notes
VTXOs can be large objects due to genesis data. Avoid excessive cloning - use references or Rc/Arc when needed.
Always call validate() on received VTXOs before trusting their data. Invalid VTXOs may return incorrect values from methods.
The point() and id() methods are used for equality comparison - two VTXOs with the same point are considered equal regardless of other fields.